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

Hi,
Can someone please tell me what anonymous subroutines are all about? I've been wading through someone elses code for months now trying to make it work better and they keep popping up...

Thanks,
Tom

Replies are listed 'Best First'.
Re: Anonymous Subroutines
by dsb (Chaplain) on Jul 30, 2004 at 13:50 UTC
    An anonymous subroutine is a reference to a subroutine. For lots of infor: perlref.

    For the quick rundown:
    Sub routines can be referenced, and then later dereferenced for access. Useful if you need to create an option handler or something:

    $opt = "opt" . $ARGV[0]; $subhash = { opt1 => sub { print "This is option one"; }, opt2 => sub { print "This is options two"; } }; # indicate a function when dereferencing with & &{$subhash->{$opt}};


    dsb
    This @ISA my cool %SIG
Re: Anonymous Subroutines
by Limbic~Region (Chancellor) on Jul 30, 2004 at 14:11 UTC
    Anonymous Monk,
    You have already been given the answer to your question, some references for more information, and a classic example (dispatch tables) of when you might use anonymous subs. I will offer my favorite - closures:
    #!/usr/bin/perl use strict; use warnings; sub countdown_iterator { my $start = shift; return sub { $start-- }; } my $countdown = countdown_iterator( 10 ); while ( my $time = $countdown->() ) { print "T - $time\n"; } print "Blast off\n";

    Cheers - L~R

Re: Anonymous Subroutines
by xorl (Deacon) on Jul 30, 2004 at 13:53 UTC
      If you put [ ] around those URLs they will be usuable as links. (The perlmonks one would preferably be [href://?node=Anonymous+Subroutine&go_button=Search], which should form a link using whichever of (www.)?perlmonks.(org|com|net) the reader is using so that their logon cookie is properly used.)
Re: Anonymous Subroutines
by cfreak (Chaplain) on Jul 30, 2004 at 13:55 UTC

    Well I'm not certain what exactly you're looking for. They are closely related to references so something like this:

    my $bar = sub { # do something here }; $bar->(); # executes the stuff in the anonymous sub above
    Is the same as:
    sub foo { # do something here } my $bar = \&foo; $bar->(); #executes the stuff in foo()

    I like to use a dispatch table in web apps that uses either anonymous subs or sub references. Like so:

    my %actions = ( foo => \&do_foo, # some long operation bar => sub { # some short one line thing }, default => sub { # do something by default }, ); my $request = $cgi->param('request'); if( exists($actions{ $request } )) { $actions{ $request }->(); } else { $actions{ default }->(); }

    Hope that gives you an idea of what's going on.

Re: Anonymous Subroutines
by FoxtrotUniform (Prior) on Jul 30, 2004 at 19:58 UTC

    Let me try to give you a different perspective on anonymous subs than you've gotten so far. (Not that what's been written is bad, wrong, or inaccurate; it's all very good stuff. But it's not the whole story.)

    Perl allows you to treat functions as first-class data objects -- you can pass them to other functions, return them, store (references to) them, and generate them on the fly. This is difficult to handle with the usual symbol table mechanism (named functions that you call just like builtins), so Perl lets you store (refs to) functions in scalars. This is where you get anonymous functions: functions that aren't in the symbol table.

    Here's an example: suppose you're turning Usenet-style text (*bold*, _italics_,, etc) into HTML-style markup. One way to do it would be to write a bunch of conversion functions:

    sub translate_bold { ... } sub translate_italics { ... } ...
    but that gets tedious pretty quick. Another way (and I'm not saying it's the best way, but it illustrates the point) is to write a function to generate the conversion functions:
    sub build_trans { my ($usenet, $tag) = @_; return sub { my ($text) = @_; # do translation here, using $usenet and $tag } }
    Then you can keep all the translation patterns in a config file, and build your translation functions on the fly:
    while (my $pat = &read_trans_pattern($cfg)) { $trans_funcs{$pat->{'usenet'}} = &build_trans_func($pat->{'usenet'}, $pat->{'tag'}); }
    Want to add support for +monospace text+? Thanks to your translation-function builder, all you have to do is add a line to your config file.

    This may seem unnecessarily complex, but what it does is keep the complexity in a small part of your code -- the translation-function builder -- rather than spread it out over dozens of functions.

Re: Anonymous Subroutines
by gmpassos (Priest) on Jul 30, 2004 at 20:34 UTC
    Basically an anonymous sub is just a sub that doesn't have a name in the package, so you just hold a reference to it, like when you make \&foo to make a reference to a sub foo {}.

    But the most usefult thing of anonymous sub is closure:

    sub foo { my ( $arg ) = @_ ; my $bar = sub { print "ARG[$arg]\n" ; return "RE[$arg]" ; } ; return $bar ; } my $bar1 = foo(123) ; my $bar2 = foo(456) ; my $foo1 = &$bar1() ; my $foo2 = &$bar2() ; print "foo1: $foo1\n" ; print "foo2: $foo2\n" ;
    Output:
    ARG[123] ARG[456] foo1: RE[123] foo2: RE[456]
    Also is useful to create functions with eval:
    my $e = 10 ; my $sub = eval(" sub { return 2**$e } ") ;
    You also can redefine a normal sub with the declaration of a anonymous sub:
    sub foo { print "foo\n" ;} # now redefining it: *foo = sub { print "bar\n" ;}
    See perlref and perlsub

    Graciliano M. P.
    "Creativity is the expression of the liberty".

Re: Anonymous Subroutines
by doom (Deacon) on Jul 31, 2004 at 09:18 UTC
    A pretty common example of a use of anonymous subroutines is the File::Find module:
    use File::Find; find(\&wanted, @directories_to_search); sub wanted { ... }
    What File::Find does for you is to descend through one or more trees of directories, and it runs some user defined code at each point through the tree. So the author designed around the idea of passing in a code reference to an arbitrary routine which can you can call anything you want. In this example it's "wanted", in another application it might be "unlink_big_files".

    (There's a strong argument that this File::Find interface was a bad idea, and it has a number of competitors these days like File::Find::Rule, but still if you're working on existing code, you're likely to see File::Find used.)

    Maybe you should try and give us a better idea of what you don't get about anonymous subs...