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)?
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)?
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"; } );
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!
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.