Loading ...
Sorry, an error occurred while loading the content.
 

Re: [PBML] Am I Understanding the Infix Dereference Operator and Shift Function Correctly?

Expand Messages
  • Charles K. Clarkson
    James E Keenan ... I have a little trouble understanding how [ [ lastname1 , firstname1 , id1 ] ] get s dereferenced. See below.
    Message 1 of 1 , Nov 29, 2001
      "James E Keenan" <jkeen@...>

      : I'd like to ask people on this list if my interpretation of the meaning of
      : some coding is correct.

      I have a little trouble understanding how
      [ [ 'lastname1', 'firstname1', 'id1' ] ]
      get's dereferenced. See below.

      : Here's the set-up: At Perl Seminar NY (perlsemny) I recently made a
      : presentation about an object-oriented module I've been writing called
      : DataPresenter whose objective is manipulation of database reports from
      : entirely within Perl. The data structure inside a DataPresenter object is a
      : hash of array references:
      :
      : my %data = [
      : 'entry 1 => ['lastname1', 'firstname1', 'id1'],
      : 'entry 2 => ['lastname2', 'firstname2', 'id2'],
      : 'entry 3 => ['lastname3', 'firstname3', 'id3'],
      : ];
      :
      : Among the methods in DataPresenter is one, select_rows(), which enables the
      : user to specify criteria by which certain entries in the data structure are
      : selected for presentation in an output format while other entries are
      : excluded. After the presentation, a perlsemny colleague suggested an
      : additional method, which I'll call select_rows_by_sub(), which takes as its
      : sole argument a reference to a subroutine in which the user evaluates each
      : entry by the selection criteria.
      :
      : # proposed new DataPresenter method
      :
      : sub select_rows_by_sub {
      : my ($self, $do_it) = @_;
      : my %data = %$self;
      : foreach my $key (sort keys %data) {
      : unless ($do_it->($data{$key})) {
      : delete $data{$key};
      : }
      : }
      : %$self = %data;
      : return $self;
      : }
      :
      : # sample user-defined subroutine
      :
      : sub mine1 {
      : my ($lastname,$firstname,$id) = @{shift()};
      : if ($lastname =~ /smith/i){
      : return 1;
      : } else {
      : return 0;
      : }
      : }
      :
      : # here's how method is called from main package
      :
      : $dp1->select_rows_by_sub(\&mine1);
      :
      : Here's what's happening. The user calls &select_rows_by_sub with 1
      : argument, reference to the user-defined subroutine &mine1. Inside
      : &select_rows_by_sub that argument is stored in the scalar $do_it. Each
      : entry in the database, $data{$key}, is examined in turn and, unless it meets
      : the selection criteria defined in &mine1, it is deleted from the object's
      : data structure.
      :
      : Here's the first point where I want to make sure that I'm understanding the
      : proposed coding. I personally have not previously used '->', the infix
      : dereference operator, to call a subroutine by reference:
      :
      : $do_it->($data{$key})
      :
      : According to the Camel book (pp 90, 253), the left-hand side of -> must be
      : subroutine dereference and the right-hand side must be a *list* of arguments
      : passed to that dereferenced subroutine. I emphasize 'list' here because
      : here we have a list of only 1 element, $data{$key} (which is itself a
      : reference to an array). Hence, when the argument comes into &mine1, its @_
      : looks like this:
      :
      : [
      : [
      : 'lastname1',
      : 'firstname1',
      : 'id1',
      : ]
      : ]
      :
      : -- an anonymous array whose sole element is a reference to an array whose
      : elements are the values for that particular entry in the data structure.
      : Those parentheses around the r.h. side of the infix operator are required.
      : You can't get away with just
      :
      : $do_it->$data{$key}
      :
      : as you then wouldn't have a list on the r.h. side of the infix operator.
      : This additional level of anonymity will, however, eventually have to be
      : stripped away.
      :
      : Now we come to the first line of &mine1:
      :
      : my ($lastname,$firstname,$id) = @{shift()};

      Here's where I get confused:
      When we enter the sub,
      @_ = ( [ [ 'lastname1', 'firstname1', 'id1' ] ] );

      shift() grabs the first element of @_:
      giving us: [ [ 'lastname1', 'firstname1', 'id1' ] ]

      @{ shift() } dereferences [ [ 'lastname1', 'firstname1', 'id1' ] ]
      giving us: [ 'lastname1', 'firstname1', 'id1' ]

      Shouldn't we have to dereference everything 1 more time?
      Perhaps with: @{ shift @{ shift() } }

      : This notation is so compact and so different from what I have seen before
      : that it took me many hours to understand it. Where, I wondered, was
      : &mine1's @_? Eventually I figured that if I re-wrote it less tersely as:
      :
      : my @temp = @_;
      : my ($lastname,$firstname,$id) = @{shift(@temp)};
      :
      : -- then I could interpret it as follows: &mine1's argument list is stored
      : in the private variable @temp. Since the list consists of just a single
      : element (what was originally $data{$key}), we can use the shift function to
      : empty the list. But since that single element is itself a reference to an
      : array, we must dereference it before assigning the elements of that array to
      : private scalars.
      :
      : We can now eliminate @temp:
      :
      : my ($lastname,$firstname,$id) = @{shift(@_)};
      :
      : and next take advantage of the fact that if a specific array is omitted as
      : the argument to shift, "the function shifts @_ within the lexical scope of
      : subroutines and formats ..." (Camel, p 785):
      :
      : my ($lastname,$firstname,$id) = @{shift()};
      :
      : -- arriving at the terse coding my perlsemny colleague proposed. The user
      : specifies the data points she wishes to match. If a match occurs, a true is
      : returned, the 'unless' condition in &select_rows_by_sub is met and that
      : particular entry remains in the object's data structure, i.e., it is
      : selected.
      :
      : Now, does the preceding explanation make sense?
      :
      : Jim Keenan
      : Brooklyn, NY
      : jkeen@...
      :
      :
      :
      :
      :
      :
      : Unsubscribing info is here:
      http://help.yahoo.com/help/us/groups/groups-32.html
      :
      : Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
      :
      :
    Your message has been successfully submitted and would be delivered to recipients shortly.