spacer

Webref WebRef   Sitemap · Experts · Tools · Services · Newsletters · About i.com

home / programming / perl / professional / chap7 / 1 11145
[previous] [next]
Developer News
Microsoft Shows Off Silverlight 4, IE9 Plans
Metasploit Expands Vulnerability Test Framework
HyperCard Reborn?

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.

home / programming / perl / professional / chap7 / 1 11145
[previous] [next]

Copyright 1999 Wrox Press Ltd. and

internet.commediabistro.comJusttechjobs.comGraphics.com

Search:

WebMediaBrands Corporate Info

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | Shopping | E-mail Offers | Freelance Jobs

webref The latest from WebReference.com Browse >
Rolling Out Your Own HTML Application Version Control · HTML 5: Client-side Storage · Working with Ajax Server Extensions
Sitemap · Experts · Tools · Services · Email a Colleague · Contact FREE Newsletters 
 The latest from internet.com
Wi-Fi Product Watch, November 2009 · Chip Market Recovering From '08 Collapse · Low-Cost Tools to Kickstart Your New Business


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


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