This article references code from the
Perl Hacks article. This is not a full discussion of prototypes. Here is some good reference material on Perl subroutine prototypes:
- Programming Perl (3rd Edition), Wall, Christiansen, Orwant. Page 225, under "Prototypes".
- From a unix shell, "perldoc perlsub". Search for the prototypes section.
- Great Article by Tom Christiansen on prototypes and their pitfalls.
In regards to the
Perl Hacks article, John posed a great question on subroutine prototypes with the & sigil, which was:
Your first example has:
sub foo (&) {
my $subref = shift;
Could you have also written the following:
sub foo (\&) {
Do they mean the same thing? Since AFAICT passing a function means
passing the reference: it makes no sense to physically pass an entire function to
another function (unless 'another function' is a code parser of some sort)
--
They almost mean the same thing. In general, a backslashed sigil in a prototype causes the implicit conversion of the argument to a reference. So if you call:
foo(@ack);
and foo was declared as such:
sub foo (\@) {
... ...
}
foo gets a reference to the @ack array as its first argument. (Foo can silently edit @ack under the hood, which as John pointed out, is one of Conway's reasons for not recommending these types of prototypes - they can be sneaky) Carry this concept onto & sigil prototypes - if a backslashed sigil causes an implicit reference for @ and %, so should it do the same for & -- which is exactly what it does.
sub foo (\&) {
my $subref = shift; ## as advertised, you get a ref to a subroutine.
$subref->();
}
Here's the critical point: when the & sigil is backslashed in the prototype, the subroutine passed in
*MUST* be a named subroutine. So in order to actually make it work, you have to have the following situation:
sub bar { .. } ## bar now lives in the current package's symbol table.
sub foo (\&) {
print "hello\n";
my $subref = shift;
$subref->();
}
# call it
foo (&bar);
Now, the unbackslashed & prototype: Just like the unbackslashed @ prototype, its magical!
The unbackslashed & prototype requires an
*anonymous* subroutine to be passed in, not a named subroutine. That is key difference #1. The second key difference is that when the & sigil is first in the prototype, as in:
sub my_map (&@) {
....
}
You get the nice syntactic sugar which allows you to call you function as:
my_map { .. .. .. .. } @some_list;
--
MattAvitable - 15 Aug 2006