4. Subroutine References and Closures
Contents:
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 ReferencesThere'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 SubroutinesWe 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 SubroutinesYou 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 ReferencesDereferencing 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 ReferencesRecall 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. |
|