PerlPhi has asked for the wisdom of the Perl Monks concerning the following question:

hi,,,currently im reading the "Intermediate Perl" book. im being bugged by the anonymous data structures. a part of the book it says that anonymous data structures are structures that do not have explicit names. so i understand (correct me if im wrong) that this "names" that is being point out, would be like ($my_ref, $var, $_, etc...) that is implicitly created by perl.

as we could see on the example below:

for (@_) { print; $_ = undef; }

we all knew that the implicit variable here is $_ that is being printed out. so in connection with creating anonymous data structures below:

my $ref = ["my","list"];

what would be that implicit name (variable) that was created? and how can i access it?

if i was wrong of pointing out that this "name" is a variable rather was a memory address, then it means:

EXPLICIT NAME: $var

IMPLICIT NAME (memory address): 0x25512

VALUE: perl

am i right? that there are two ways to access a value, by using the explicit name, and through an implicit name.

thanks in advance... keep deep and dark!

From: PerlPhi

Replies are listed 'Best First'.
Re: Anonymous Data Structures
by bart (Canon) on Jun 01, 2007 at 10:51 UTC
    Anonymous hashes and anonymous arrays actually have a poor name. Actually, they are just hash resp. array references. But you can write them directly, as an expression, without having to populate a real (named) hash or array first. And that is all. You shouldn't look for more behind it all, because there is nothing.

    For Perl,

    $aref = [ 'a', 'b' ]; $href = { 'foo' => 123 };
    is equivalent to
    $aref = do { my @a = ('a', 'b'); \@ }; $href = do { my %h = ('foo' => 123); \%h };
    You end up with just a hashref and an arrayref, and nothing else.

    So, a better name for them would be "anonymous hash ref" and "anonymous array ref", IMO.

    And no, there are no implicit names. Perl doesn't use the names internally. It doesn't need them.

    And perhaps you could look into typeglobs and stashes (Symbol Table hASHES), you might find it interesting. (Best discussion I found is in the old, 1st edition of the O'Reilly book "Advanced Perl Programming"; the second edition is a different book.)

Re: Anonymous Data Structures
by shmem (Chancellor) on Jun 01, 2007 at 11:14 UTC
    The difference between named and anonymous data lies in the way how they are stored and addressed:
    Named Anonymous @array [] %hash {}

    If you say somewhere in your code

    @array;

    the named array @array is created, and it's there, you can use it later to stuff things in. Whereas if you say

    [];

    you create an anonymous array, and on the next line it's gone. Why? The creation of an anonymous array returns a pointer to where that array is allocated. If you don't store that pointer somewhere, it's gone, and the anonymous array too. If you create a named array, the array is "contained in the name", for anonymous arrays you have to store its location somewhere:

    $arrayref = [];

    Now you have the reference to that anonymous array in you scalar variable $arrayref, and you can pass this pointer around, or fill the anonymous array pointed at by dereferencing it:

    $ary = $arrayref; push @$ary,"foo"; print $arrayref->[0]; # prints "foo" \ print @$arrayref[0]; # prints "foo" - same pointer value in $ary and +$arrayref print $ary->[0]; # prints "foo" /

    So a named array has a name, which is the word after the sigil '@', while an anonymous array only has a location somewhere in perl's memory.

    we all knew that the implicit variable here is $_ that is being printed out.

    This "implicit variable" has nothing to do with an array, but with the for iterator. You can use that with literals too:

    for("foo") { print; # prints foo undef $_; # dies with "Modification of a read-only value attempte +d" # - literals cannot be modified }

    The variable $_ is not attached to an array, it just happens to be the global default variable a.k.a The Thing (which in a for loop is aliased, so for works with its own version and doesn't stomp on other operator's idea of what $_ is).

    so in connection with creating anonymous data structures below:
    my $ref = ["my","list"];
    what would be that implicit name (variable) that was created? and how can i access it?

    There is no implicit name - all there is is a pointer. If you force that pointer to be a string (e.g. by saying print $ref), perl translates the pointer into something readable (e.g. ARRAY(0x8166c28)).

    All you have is a scalar variable $ref, to which you assigned the pointer to an anonymous array. You have to dereference that address pointer if you want to loop over the anonymous array - the loop body is exactly the same:

    for (@$ref) { print; $_ = undef; } # the [] array pointed to with the content of $ref is now [undef,undef +]

    See perlref for further information.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Anonymous Data Structures
by Herkum (Parson) on Jun 01, 2007 at 11:07 UTC

    I had to look up anonymous data structures to figure out what you were referring to and it appears that they are just talking about references. THAT I can help you with.

    Normally there are two ways of working with a variable, making a copy of it, or using a reference to it. A simplified example would be a sign-in sheet for a writing class. You want everyone to write their name on the sheet so you have to get information from everyone. There are two ways of doing this,

    • Make a copy of it.
      1. make a copy of the sign-in sheet.
      2. have the student sign the sheet new copy.
      3. Get the copy back from the student.
      4. Throw away the old sign-in sheet and go back to step 1. Repeat until finished
    • Use a reference
      1. Take a sign-in sheet.
      2. Have the student sign their new on the sign-in sheet
      3. Repeat until finished.

    The first way sounds stupid, but you will be surprised how often it occurs, especially with beginners. Here is code to show how it works.

    #!/usr/bin/perl use strict; use warnings; # Make a copy of a variable my $counter = 0; print "Copying and replacing the variable\n"; for (1..10) { $counter = increment_number( $counter ); print "Count is $counter\n"; } $counter = 0; print "Passing a reference to the variable\n"; for (1..10) { increment_number( \$counter ); print "Count is $counter\n"; } sub increment_number { my $number = shift; if (ref $number eq 'SCALAR') { $$number++; return; } return ++$number; }
      Hi Herkum, So colour me a noob, but what you are saying is in your first example we are chewing up memory creating a copy of $counter. Whereas in the second example we are pointing to the original. The implication being that example two is more efficient/faster/leet? Is that right. Lance

      Kia Kaha, Kia Toa, Kia Manawanui!
      Be Strong, Be Brave, Be perservering!

        your first example we are chewing up memory creating a copy of $counter

        Correct.

        in the second example we are pointing to the original. The implication being that example two is more efficient/faster/leet? Is that right.

        Correct as well. The example I used does not really offer any performance benefits because it is too small.

        Lets supposed you have a million element array. In the first example you would, create 2 copies of that million element array in your program(So it takes more memory). You would also be passing million values to and from the function(so it would be slower).

        If you use a reference you have one copy of that array. You only passing a single value to the function. This can be provide enormous performances benefits when working with a large amount of data.

        There are times you want to make a copy because you don't want to change the original data. But if you are modifying the original values you should use references.

Re: Anonymous Data Structures
by FunkyMonk (Bishop) on Jun 01, 2007 at 11:12 UTC
    Anonymous hashes & arrays, as you stated, are just hashes and arrays that don't have a name. They are only useful when used as a reference:

    my $hashref = { A => 1, B => 2 }; my $arrayref = [ 1, 2, 3 ];

    You would then access the elements of the references using ->:

    print $hashref->{B}; # 2 print $arrayref->[2]; # 3

    or by

    print %$hashref{B}; # 2 print @$arrayref[2]; # 3

    I much prefer ->, for what it's worth

      I much prefer ->, for what it's worth

      As a general rule, /me too. Though as with most things, there are situations in which it is best suited and situations in which the other way is preferable. Also, they're not equivalent in all respects.

Re: Anonymous Data Structures
by agianni (Hermit) on Jun 01, 2007 at 15:23 UTC

    Does it really have to be a ref to be anonymous though? The most common use of anonymous arrays and hashes for me is in return values for subs:

    sub foo{ return { bar => 'baz' }; }

    You could just as easily return an anonymous hash:

    sub foo{ return ( bar => 'baz' ); }

    The other common place to see anonymous hash and array refs (always refs in this case) is in constuction of multi-dimentional data structures:

    my $foo = [ { bar => 'baz' }, ];

    So the arrayref isn't anonymous, but the hashref that is the first (and only element) is.

    perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'

      You could just as easily return an anonymous hash:

      sub foo{ return ( bar => 'baz' ); }

      That is not a hash, but a list (in fact all subs only return lists) suitable for being assigned to a hash, period.

        Fair enough. My point was simply that it needn't be a reference to be an anonymous data structure.
        perl -e 'split//,q{john hurl, pest caretaker}and(map{print @_[$_]}(joi +n(q{},map{sprintf(qq{%010u},$_)}(2**2*307*4993,5*101*641*5261,7*59*79 +*36997,13*17*71*45131,3**2*67*89*167*181))=~/\d{2}/g));'