Advanced Perl Programming

Advanced Perl ProgrammingSearch this book
Previous: 3.4 Filehandles, Directory Handles, and FormatsChapter 4Next: 4.2 Using Subroutine References
 

4. Subroutine References and Closures

Contents:
Subroutine References
Using Subroutine References
Closures
Using Closures
Comparisons to Other Languages
Resources

Many are called, but few are called back.

- Sister Mary Tricky

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:

In the following sections, we look at the syntax for taking and managing subroutine references and subsequently use them in the applications listed.

4.1 Subroutine References

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.

4.1.1 References to Named Subroutines

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 0 (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.

4.1.2 References to Anonymous Subroutines

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.

4.1.3 Dereferencing Subroutine References

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:

$rsub->(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";
}

4.1.4 Symbolic References

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.


Previous: 3.4 Filehandles, Directory Handles, and FormatsAdvanced Perl ProgrammingNext: 4.2 Using Subroutine References
3.4 Filehandles, Directory Handles, and FormatsBook Index4.2 Using Subroutine References