I want to write a function whose first parameter is a description, and the second parameter is a code block. I want the finished code to read like:
verify "description" { boolean-assertion-block };
I'm specifically looking to avoid the sub
keyword.
I can put the description AFTER the code block, no problem:
sub verify (&$) { ... }
But when I reverse the prototype symbol order:
sub verify ($&) { ... }
Then I get an error message:
Type of arg 2 to main::verify must be sub {} (not anonymous hash ({})) at ...
Clearly, Perl has special handling for the first argument being a code block.
So, maybe I can make it a curried function?
sub verify ($) {
my $message = shift;
return sub (&) { . . . }
}
But then I get a syntax error between the description and the code block:
syntax error at ... near ""..." { "
I tried altering the calling syntax to try to help out the compiler:
test "...", { BLOCK };
test("..."){ BLOCK };
test("...")({ BLOCK });
( test "..." )({ BLOCK });
No joy. Can Perl even do what I want to do?
The (&)
prototype only has such niceness when used for the first argument in a sub. From perldoc perlsub
:
The interesting thing about "&" is that you can generate new syntax with it, provided it's in the initial position
One way to provide a similar level of niceness would be:
sub verify ($%) {
my ( $message, %opts ) = @_;
my $coderef = $opts{using};
...;
}
sub using (&) {
my ( $coderef ) = @_;
return ( using => $coderef );
}
# The `verify` sub accepts a name followed by a hash of options:
#
verify(
"your message here",
"using" => sub { ... },
);
# The `using` sub returns a two-element list that will satisfy
# that hash of options:
#
verify "your message here", using {
...;
};
If you desperately want to allow a syntax exactly like:
verify "description" { boolean-assertion-block };
... then it is still possible, but requires the dark arts. Keyword::Simple is probably your best bet, but Devel::Declare and Filter::Simple are options.