FiniWiki, Powered by Foswiki Free and Open Source Wiki
RichmondPM > PerlPrototypes
FiniWiki webs: Main | System | Sandbox   Login or Register
Users | Groups | Offices | Changes | Index | Search | Go
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! smile 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

Parents: WebHome
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding FiniWiki? Send feedback