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

I'm wondering about anonymous arrays/hashes/subs. I see in the Camel book how they're supposed to work(what with the {} composers and all), but I have a few questions.

* Why would you want such a thing?
* What's the scope on an anonymous thingie?
* Will they ever die/get lost/get clobbered?

---
A fair fight is a sign of poor planning.

Replies are listed 'Best First'.
Re: Anonymous Thingies
by davido (Cardinal) on Oct 21, 2003 at 20:17 UTC
    In their simplest form, anonymous thingies might not at first seem all that helpful. As you get familiar with them you will see that they are indispensable in many situations. Remember that a multidimensional array is actually an array of references to arrays. You wouldn't want to have to maintain names in the symbol table for all those sub elements. Look at this example:

    my @array1 = (1, 2, 3, 4); my @array2 = (5, 6, 7, 8); my @master_array = ( \@array1, \@array2 );

    Great, now you have a 2d array, and you can dereference it like this:

    print $master_array[0][2], "\n"; # prints '3'

    But what a pain, having to keep track of all those @array1, @array2, etc. And even more of a pain it is if somehow you modify an element in @array1, and forget that it is going to propigate through to the same element within @master_array.

    So there's an easier way.....

    my @master_array = ( [1, 2, 3, 4], [5, 6, 7, 8] );

    Now you have the same contents in @master_array: a two dimensional array. But you also have completely bypassed all the trouble of creating temporary sub-arrays. In this example, @master_array contains two anonymous arrays of four elements each.

    You can take it a step further. Perhaps you have a function that takes an array ref as parameter. Maybe you don't need that array to ever have a real name, just a reference to it. So that's when you would use an anonymous array as the top level of the structure.

    As for scoping, as long as someone knows about the anonymous array, it remains in existance. By "knows about", I mean, as long as something refers to it, and that something is still in scope, the anonymous array will remain alive and there. Perl uses a "reference count" method of garbage collection. Each time something points to a piece of information, that piece of information (the scalar, or whatever) has one added to its reference count. As the things that point to it fall from scope or get pointed elsewhere, the reference count drops. It's not until nothing is pointing to (or referencing) it that it gets 'reaped'.

    The same principles apply to other anonymous thingies such as hashes and functions too. Imagine how useful it is to be able to utilize complex data structures by virtue of anonymous thingies.

    References don't care whether the thing they point to has a name in the symbol table or not. As long as the thingy has a positive reference count, it will remain in existance.

    I strongly recommend looking at the following resources that are available online or at your local Perl installation:

    • perlreftut: A tutorial on references.
    • perldsc: "Data structure cookbook".
    • perllol: A description of 'lists of lists'.
    • perlref: A more in-depth overview of references.

    At some point through that reading assignment a lightbulb will come on and you'll say, "Oh, that makes sense."

    To directly respond to your questions.....

    * Why would you want such a thing?
    * What's the scope on an anonymous thingie?
    * Will they ever die/get lost/get clobbered?

    • Because they allow difficult things to be made easy.
    • The scope is equal to the scope of the things that know about the anonymous thingy. As long as something that knows about it is in scope, it remains in scope.
    • They only die and get clobbered when you let their reference count drop to zero. That happens when the last reference to them falls from scope or is redirected elsewhere. They will only get lost if the last reference to them is disconnected. And then instead of getting lost they evaporate. ;)

    Dave


    "If I had my life to do over again, I'd be a plumber." -- Albert Einstein
Re: Anonymous Thingies
by jeffa (Bishop) on Oct 21, 2003 at 20:03 UTC
    One of the first "things" that pops in my mind as to why i would want an anonymous data structure is using HTML::Template ... or DBI for that matter. With the former, you have to pass a complex data structure like so:
    $ref = { value => 'some single value', loop => [ { name => 'foo', id => 5 }, { name => 'bar', id => 9 }, ], };
    The 'loop' key points to an anonymous list which in turns contains a list of anonymous hash references. The scope of each of these anonymous things last as long as $ref itself, as long as you don't delete them, of course.

    In short, anonymous data structures (and subroutines) are among the most useful items Perl has to offer. I am sure that others will give you lots of closure and callback examples to show off the usefulness of anonymous subroutines. I have to get back to work now ... eduardo is giving me "the stare" ...

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
Re: Anonymous Thingies
by pg (Canon) on Oct 21, 2003 at 20:18 UTC

    This question can be understood at two different levels:

    • Are those anonymous stuffs necessary in theory, in order to form a complete language? That’s a big question, and can well start a thread of interesting discussion here. However you might love to have them any way, for flexibility, performance...
    • As we got those things in Perl already, does one really need to use them? Yes, and some times you are forced to use them. Here is one example where you are forced to use anonymous sub: You can do this in Tk:
      $mw->Button(command => \&func1)->pack;
      but if func1 is a method of a class, you will not be able to say
      $mw->Button(command => \&$self->func1)->pack;
      and you have to say:
      $mw->Button(command => sub {\&$self->func1})->pack;
Re: Anonymous Thingies
by hanenkamp (Pilgrim) on Oct 21, 2003 at 20:58 UTC

    Why would you want such a thing?

    Frequently. Since Perl flattens lists:

    @x = ( (1, 2, 3), ('a', 'b', 'c') );

    is equivalent to:

    @x = (1, 2, 3, 'a', 'b', 'c');

    Anonymous hashes/arrays are essentially used prevent this from being done.

    What's the scope on an anonymous thingie?

    To quote the Camel Book:

    Anonymous: Used to describe a referent that is not directly accessible through a named variable. Such a referent must be indirectly accessible through at least one hard reference. When the last hard reference goes away, the anonymous referent is destroyed without pity.

    That is, it goes away immediately if it isn't assigned to be referenced by something.

    Will they ever die/get lost/get clobbered?

    Perl 5 uses reference counting for garbage collection. As soon as the reference count on the reference goes to zero, it will be "destroyed without pity." Therefore, the statement:

    [ qw(I am not assigned to anything.) ];

    Get's canned immediately, while:

    $var_a = $var_b = $var_c = [ qw(I am referenced thrice!) ];

    lasts until all three variables go out of scope or are assigned different values or, ultimately, when the interpreter exits if one of these is global or never goes out of scope and is never reassigned.

Re: Anonymous Thingies
by samtregar (Abbot) on Oct 21, 2003 at 21:30 UTC
    The above replies are all well and good, but they're mostly telling you what references are good for. Since you just asked what anonymous variables are for, I thought I'd provide a more direct answer: brevity.

    Simply put, there's nothing you can do with an anonymous thing that you couldn't just as well do with a named thing. For example, to create a reference to a hash of arrays I could:

    my @array_one = (1, 2, 3); my @array_two = (3, 4, 5); my %hash = (one => \@array_one, two => \@array_two); my $ref = \%hash;

    But it's so much nicer to be able to just say:

    my $ref = {one => [ 1, 2, 3 ], two => [ 3, 4, 5 ]};

    -sam

    PS: Actually, it occurs to me that this isn't quite true with subs, since you can't do 'my sub foo' and get a lexically scoped sub named foo. As such anonymous subs are your only way to make new sub routines at runtime without resorting to eval.

Re: Anonymous Thingies
by nevyn (Monk) on Oct 21, 2003 at 21:15 UTC
    Why would you want such a thing?

    Probably the simpest example I can think of is when you "need" to pass more than one array or hash (or one of each) to a function. Then you need to pass a reference, and sometimes you are either getting the array from a function or want to hard code it. So you have...

    # Passing array refs from function returns... foo([split(',', $a)], [split('/', $b)]); # Passing hard coded data (used in CGI etc.) bar([1..4], { 1 => "foo", 2 => "bar", 3 => "abcd", 4 => "xyz"});
    What's the scope on an anonymous thingie?

    Probably the easiest thing to do is think of them as named variables, but the names are not in scope, so...

    # "anonymous" reference to array of 8 my $foo = [1..8]; ## Is the same as... my $foo = undef; # New scope... { # Array of 8 my @foo = (1..8); # Create reference to array of 8 $foo = \@foo; }

    In both cases doing a $foo = undef; will get rid of the last reference to the array.

    -- James Antill
Re: Anonymous Thingies
by jonadab (Parson) on Oct 22, 2003 at 02:53 UTC

    The most obvious uses have already been pointed out, but I'd like to mention one other: closures.

    When an anonymous subroutine holds references to a lexically scoped variable, and a reference to the subroutine is kept after the lexical variables pass out of scope, the result is a closure: those lexical variables are now held only by that anonymous sub. You can create an entire object system this way, if you are so inclined, or you can just pass around coderefs that hold state. This allows a routine to have a persistent local variable that keeps its value between calls. Further, if the code that creates the closure gets called multiple times, it creates multiple closures -- each with its own variables. Unfortunately, I don't have a really good example of this to give you, because all the nodes I've posted so far that use this technique are obfuscated and so don't make very clear examples. Sorry about that. But it is possible to use this same effect in much cleaner, nicer, better-looking, and more maintainable code. Maybe someone else can give you a good legible example.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Anonymous Thingies
by injunjoel (Priest) on Oct 22, 2003 at 01:09 UTC
    Greetings all,
    Here are my thoughts:

    * Why would you want such a thing?
    my ANSWER = "to create complex/nested data structures without cluttering up your script with single use variables: i.e. hashes of arrays containing hashes... among other things";

    * What's the scope on an anonymouse thingie?
    my ANSWER = "the scope is the same as with other named data structures, use strict and you will see any potential issues";

    * Will they ever die/get lost/get clobbered?
    my ANSWER = "reflect on my potential answer to the scope issue";

    Hows that for short and simple.
    Personally I use anonymous 'thingies' on a daily basis for nested data structures. Good scripting inheres in well packaged data... but thats just my opinion.

Re: Anonymous Thingies
by imcsk8 (Pilgrim) on Oct 22, 2003 at 03:02 UTC
    * Why would you want such a thing?

    anonymous hashes and arrays are useful in some situations, for example yo can use a reference to a anonymous hash to store configuration of your program in a file, so you only require the file in the progam and you have the configuration, no need for parsing file you have all in native perl data structures; other use is when you are creating objects, an anonymous (again a reference) hash (or array sometimes) can be used to store the properties of the object; there are other uses but this ones are the ones i use more often.


    * What's the scope on an anonymous thingie?

    the same of the non anonymous, the block or the package depends on how you are you scoping them.


    * Will they ever die/get lost/get clobbered

    don't understand too well this question but i if you are asking if they are going to be deprecated i don't think so.


    i hope this helps
    ignorance, the plague is everywhere
    --guttermouth