How do I properly invoke a subroutine that takes 2 subroutine references?
Imagine this subroutine:
sub test(&&)
{
my $cr1 = shift;
开发者_运维问答 my $cr2 = shift;
$cr1->();
$cr2->();
}
I know I can call it like: test(\&sub1,\&sub2)
, but how can I call it like:
test { print 1 },{ print 2 };
If I say that the subroutine takes only one &
, than sending a block will work. I don't know how to make it work with 2.
If I try to run it like that, I get:
Not enough arguments for main::test at script.pl line 38, near "},"
EDIT: is there no way of invoking without sub
?
You need to explicitly say
test( sub { print 1 }, sub { print 2 } );
or
test { print 1 } sub { print 2 };
The implicit "sub" is only available for the first argument. http://perldoc.perl.org/perlsub.html#Prototypes:
An & requires an anonymous subroutine, which, if passed as the first argument, does not require the sub keyword or a subsequent comma.
Some things use an extra word in there to fake it:
test { print 1 } against { print 2 };
sub against (&) { $_[0] }
sub test (&@) { ... }
but I've never liked that much.
You can do this:
test(sub { print 1 }, sub { print 2 });
I've got the following code in one of my programs:
sub generate($$$$)
{
my ($paramRef, $waypointCodeRef, $headerRef,
$debugCodeRef) = @_;
...
&$headerRef();
...
my $used = &$waypointCodeRef(\%record);
And I call it with
CreateDB::generate(\%param, \&wayPointCode, \&doHeader, \&debugCode);
If you really want to bend the syntax more then take look at Devel::Declare
Examples of modules that use Devel::Declare
:
MooseX::Declare
(GitHub repo)Test::Class::Sugar
(GitHub repo)PerlX::MethodCallWithBlock
(GitHub repo)
Full list of modules on CPAN dependant on Devel::Declare can be found via CPANTS
Here is example from Test::Class::Sugar pod:
use Test::Class::Sugar;
testclass exercises Person {
# Test::Most has been magically included
startup >> 1 {
use_ok $test->subject;
}
test autonaming {
is ref($test), 'Test::Person';
}
test the naming of parts {
is $test->current_method, 'test_the_naming_of_parts';
}
test multiple assertions >> 2 {
is ref($test), 'Test::Person';
is $test->current_method, 'test_multiple_assertions';
}
}
Test::Class->runtests;
And here is something sexy from PerlX::MethodCallWithBlock pod:
use PerlX::MethodCallWithBlock;
Foo->bar(1, 2, 3) {
say "and a block";
};
Devel::Declare is a much more robust and saner way of contorting your Perl code compared to using a source filter like Filter::Simple
.
Here is a video from its author which may help a bit more.
/I3az/
精彩评论