Professional Perl | 5 | WebReference

Professional Perl | 5

11145
[previous] [next]

Professional Perl

Anonymous Subroutines and Subroutine References

Less common than named subroutines, but just as valid, are anonymous subroutines. As their name suggests, anonymous subroutines do not have a name. Instead they are used as expressions, which return a code reference to the subroutine definition. We can store the reference in a scalar variable (or as an element of a list or a hash value) and then refer to it through the scalar:

my $subref = sub {print "Hello anonymous subroutine";};

In order to call this subroutine we use the ampersand prefix. This instructs Perl to call the subroutine whose reference this is, and return the result of the call:

# call an anonymous subroutine
&$subref;
&$subref ("a parameter");

This is one of the few places that an ampersand is still used. However, even here it is not required, we can also say:

$subref->();
$subref->("a parameter");

These two variants are nearly, but not quite, identical. Firstly, &$subref; passes the current @_ array (if any) directly into the called subroutine, as we briefly mentioned earlier. Secondly, the ampersand disables any prototypes we might have defined for the subroutine. The second pair of calls retains the prototype in place. (We cover both of these points later in the chapter.)

We can generate a subroutine reference from a named subroutine using the backslash operator:

my $subref = \&mysubroutine;

This is more useful than one might think, because we can pass a subroutine reference into another subroutine as a parameter. The following simple example demonstrates a subroutine taking a subroutine reference and a list of values, and returning a new list generated from calling the subroutine on each value of the passed list in turn:

#!/usr/bin/perl 
# callsub.pl
use warnings;
use strict;
sub do_list {
   my ($subref, @in) = @_;
   my @out;
   map {push @out, &$subref ($_)} @in;
   return @out;
}
 
sub add_one {
   return $_[0] + 1;
}
$, = ",";
print do_list (\&add_one, 1, 2, 3);   #prints 2, 3, 4

Some Perl functions (notably sort), also accept an anonymous subroutine reference as an argument. We do not supply an ampersand in this case because sort wants the code reference, not the result of calling it. Here is a sort program that demonstrates the different ways we can supply sort with a subroutine. The anonymous subroutine appearing last will not work with Perl 5.005:

#!/usr/bin/perl 
# sortsub.pl
use warnings;
use strict;
# a list to sort
my @list = (3, 4, 2, 5, 6, 9, 1);
# directly with a block
print sort {$a cmp $b} @list;
# with a named subroutine
sub sortsub {
    return $a cmp $b;
}
print sort sortsub @list;
# with an anonymous subroutine
my $sortsubref = sub {return $a cmp $b;};
print sort $sortsubref @list;

Of course, since we can get a code reference for an existing subroutine we could also have said:

$sortsubref = \&sortsub;

The advantage of using the anonymous subroutine is that we can change the subroutine that sort uses elsewhere in the program, for example:

# define anonymous subroutines for different sort types:
$numericsort = sub {$a <=> $b};
$stringsort = sub {$a cmp $b };
$reversenumericsort = sub {$b <=> $a};
# now select a sort method
$sortsubref = $numericsort;

The disadvantage of this technique is that unless we take care to write and express our code clearly, it can be very confusing to work out what is going on, since without running the code it may not always be possible to tell which subroutine is being executed where. We can use print $subref to print out the address of the anonymous subroutine, but this is not nearly as nice to read as a subroutine name.

It is also possible to turn an anonymous subroutine into a named one, by assigning it to a typeglob. This works by manipulating the symbol table to invent a named code reference that Perl thereafter sees as a subroutine definition. This leads to the possibility of determining the actual code supported by a subroutine name at run-time, which is handy for implementing things like state-machines. This will be covered more fully in 'Manipulating the Symbol Table Directly' in Chapter 8.

11145
[previous] [next]

and
Created: March 8, 2001
Revised: March 8, 2001

URL: https://webreference.com/programming/perl/professional/chap7/