Many are called, but few are called back.
As with ordinary variables, subroutines can be named or anonymous, and Perl has a syntax for taking a reference to either type. Such references work rather like pointers to functions in C, and they can be used to create such sophisticated structures as the following:
Dispatch tables. Or data structures that map events to subroutine references. When an event comes in, a dispatch table is used to look up the corresponding subroutine. This is useful in creating large and efficient switch statements, finite state machines, signal handlers, and GUI toolkits.
Higher-order procedures. A higher-order procedure takes other procedures as arguments (like the C library procedure
qsort
) or returns new procedures. The latter feature is available only in interpreted languages such as Perl, Python, and LISP (hey, LISPers, you have lambda functions!).Closures. A closure is a subroutine that, when created, packages its containing subroutine’s environment (all the variables it requires and that are not local to itself).
In the following sections, we look at the syntax for taking and managing subroutine references and subsequently use them in the applications listed.
There’s nothing particularly fancy or magical about subroutine references. In this section, we’ll study how to create references to named and anonymous subroutines and how to dereference them.
We saw earlier that to take a reference to an existing variable, we
prefix it with a backslash. It is much the same with subroutines.
\&mysub
is a reference to
&mysub
. For example:
sub greet { print "hello \n"; } $rs = \&greet; # Create a reference to subroutine greet
It is important to note that we are not calling
the greet
subroutine here, in the same way that we
don’t evaluate the value of a scalar when we take a reference
to it.
Contrast this to the following code, which uses parentheses:
$rs = \&greet();
This expression likely doesn’t do what you expect. It calls
greet
and produces a reference to its
return value, which is the value of the last
expression evaluated inside that subroutine. Since
print
executed last and returned a 1 or a
(indicating whether or not it was successful in printing the value),
the result of this expression is a reference to a scalar containing 1
or 0! These are the kind of mistakes that make you wish for
type-safety once in a while!
To summarize, do not use parentheses when taking a subroutine reference.
You can create an anonymous subroutine simply by omitting the name in a subroutine declaration. In every other respect, the declaration is identical to a named one.
$rs = sub { print "hello \n"; };
This expression returns a reference to the newly declared subroutine. Notice that because it is an expression, it requires the semicolon at the end, unlike the declaration of a named subroutine.
Dereferencing a subroutine
reference calls the subroutine indirectly. As with data references,
Perl does not care whether $rs
is pointing to a
named or an anonymous subroutine; dereferencing works the same way in
either case.
It should come as no surprise that prepending $rs
with the appropriate prefix—
"&
“, in this
case—dereferences it:
&$rs(10, 20); # Call the subroutine indirectly
That’s all there is to it.
Just as you can use the ->
syntax with arrays
or hashes ($ra->[10]
or
$rh->{'k2'}
), you can call subroutines
indirectly through references, like this:
$rs->(10);
In fact, subroutine calls can be chained if the intermediate calls return subroutine references. For example:
$rs = \&test1; $rs->("Batman")->("Robin"); # Prints "Batman and Robin" sub test1 { my $arg = shift; print "$arg"; return \&test2; } sub test2 { my $arg = shift; print " and $arg\n"; }
Recall that symbolic references contain names (strings), not real references. There is no difference in syntax between real and symbolic references. Consider
sub foo { print "foo called\n" } $rs = "foo"; &$rs(); # prints "foo called"
Using symbolic references is a mite slower than using real references.
Get Advanced Perl Programming now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.