views:

81

answers:

3

mysub gets a subroutine reference as its first argument.

Can I simply call mysub(sub{some subroutine body here}) ? I.e. define an anonymous subroutine right at the call?

Is the syntax OK (is it really a reference to sub that is passed)?

+3  A: 

What happened when you tried it? That's surely the best way to test whether things like this work.

But, yes, that syntax will work just fine.

#!/usr/bin/perl

use strict;
use warnings;

sub run_sub {
  shift->();
}

run_sub( sub { print "hello\n"; } );
davorg
+2  A: 

Alternatively (to the answer by @davorg), you can use:

sub run_sub
{
    my($funcref) = @_;
    &$funcref();
}

More verbose, certainly; also a little clearer, I think. But this is Perl - TMTOWTDI!

Jonathan Leffler
`$funcref->()` is a little more Modern Perlish, but I think they are absolutely identical.
Ether
Simon
FM
Right you are, sir.
Simon
+2  A: 

Since passing subroutine references to other subroutines is a fairly common pattern, Perl even has a few syntax tricks to make it even smoother:

sub function1 {          # normal declaration, implicit `(@)` prototype
    my $code = shift;
    $code->(@_);
}

sub function2 (&@) {     # prototyped declaration
    my $code = shift;
    $code->(@_);
}

function1 has to be called as: function1 sub{...}, any_other_args

function2 has the prototype (&@) which tells the compiler to impose subroutine context on the first argument (and then accept any number of additional arguments).

So you can call it as function2 {...} any_other_args which mirrors the way the higher order builtins like map, grep, and sort take their code blocks. Note that there is no comma after the code block, just like with the bultins.

You can find more information about prototypes here: http://perldoc.perl.org/perlsub.html#Prototypes

Keep in mind that Perl's prototypes are NOT for argument validation, they are hints to the compiler that allow you to write subroutines that behave like builtins.

Eric Strom