views:

898

answers:

7

I'm just curious why one would choose to use an anonymous subroutine, versus a named one, in Perl. Thanks.

+9  A: 
innaM
Of course, you can store named ('nonymous'?) subs in a variable too...my $var = \
ijw
Of course, I was exaggerating a bit for a more dramatic effect.
innaM
+7  A: 

Callbacks and generators come to mind. An example:

#!/usr/bin/perl

use strict;
use warnings;

sub generate_multiplier {
    my ($coef) = @_;

    return sub { 
        my ($val) = @_;
        $coef * $val;
    }
}

my $doubler = generate_multiplier(2);
my $tripler = generate_multiplier(3);

for my $i ( 1 .. 10 ) {
    printf "%4d%4d%4d\n", $i, $doubler->($i), $tripler->($i);
}

__END__

C:\Temp> v
    1   2   3
    2   4   6
    3   6   9
    4   8  12
    5  10  15
    6  12  18
    7  14  21
    8  16  24
    9  18  27
   10  20  30
Sinan Ünür
+1  A: 

First: sub thing is a sub. my $thing=sub... is a sub reference stored in a variable.

Second: There's a subtle usage difference:

use strict;
use warnings;

sub xx {
  my $zz=1;

   sub yy {
      print $zz;
   }
}


perl tmp.pl
Variable "$zz" will not stay shared at tmp.pl line 8.

Change [sub yy ...] to [my $yy = sub {...] or [local *yy = sub{...] and the complaint goes away.

Also, to be honest, references-to-subs are just easier to deal with, much the same as @x=(1,2,3) versus $x=[1, 2, 3].

ijw
+2  A: 

The canonical answer for anonymous subroutine is usually the numeric sorting of an array :

my @sorted_array = sort { $a <=> $b } @array;

The { $a <=> $b } represents an anonymous subroutine.

Steve Schnepp
+3  A: 

"Anonymous" subroutines are really similar to regular, named subroutines except that they aren't bound to a name in the symbol table.

sub Foo { stuff() }

BEGIN { *Foo = sub { stuff() } }  # essentially equivalent

In the second case, the "anonymous" subroutine is created and then bound to the name "Foo" in the current namespace. The BEGIN block makes it happen at compile time, just like how a named subroutine is treated. (It's a little more complicated in that the first case gives it a name that will show up in a stack trace.)

Anonymous subroutines are useful any time you want to create a function at run-time. This is particularly good for "closures" -- functions that "remember" their lexical context. For example, turning a list into an iterator:

use 5.010;
use strict;
use warnings;

sub make_iterator {
  my @list = @_;
  return sub { shift @list }; # new sub that 'remembers' @list
}

my $iter1 = make_iterator( 0 .. 10 ); 
my $iter2 = make_iterator( 'a' .. 'z' );

say $iter1->();  # '0'
say $iter1->();  # '1'
say $iter2->();  # 'a'

For a lot more on why anonymous subroutines are useful, I recommend the book Higher Order Perl which describes various techniques and applications of functional programming in Perl.

xdg
A: 

Here's an example from my rewrite of Nasm's version.pl

# jump table to subroutines / variables
my %jump = (
  id     => 'id',
  xid    => 'xid',
  hex_id => 'xid',

  h      => \&h,
  mac    => \&mac,
  sed    => \&sed,
  make   => \&make,
  nsis   => \&nsis,

  perl   => \&perl,
  dump   => \&perl,
  yaml   => \&yaml,
  yml    => \&yaml,
  json   => \&json,
  js     => \&json,

  help   => \&help,
  usage  => sub{
    require Pod::Usage;

    Pod::Usage::pod2usage(
      "run perldoc $0 or pod2text $0 for more information"
    );
  }
);

Basically the only reason I can think of is for calbacks, or for a jump table.

Brad Gilbert
+2  A: 

I talk about anonymous subroutines and why you would use them in Mastering Perl. In short, you start thinking about behavior as just another form or data just like you think about strings or numbers. When you are comfortable with that idea, you can do some pretty amazing things because you can push off a lot of decisions to very late in the program and you don't have to contort your code design to deal ahead of time with every situation that might show up.

You can write code knowing that you are going to run a subroutine, only you don't know which one yet. You trust the previous steps to work that out for you. Once you can do that, you're on another level of programming that feels like you're writing code to create your program for you. Some programming problems become much easier to solve this way.

And, like every other feature, you can take this too far or use it inappropriately.

brian d foy