英文:
Perl function that takes a BLOCK as the second parameter?
问题
我想编写一个函数,其第一个参数是描述,第二个参数是代码块。我希望最终的代码看起来像这样:
verify "description" { boolean-assertion-block };
我特别想避免使用 sub
关键字。
如果我将描述放在代码块之后,没有问题:
sub verify (&$) { ... }
但是当我反转原型符号的顺序时:
sub verify ($&) { ... }
然后我会得到一个错误消息:
Type of arg 2 to main::verify must be sub {} (not anonymous hash ({})) at ...
显然,Perl对第一个参数是代码块时有特殊处理。
所以,也许我可以将它变成柯里化函数?
sub verify ($) {
my $message = shift;
return sub (&) { . . . }
}
但是然后我会在描述和代码块之间得到语法错误:
syntax error at ... near "" { "
我尝试更改调用语法以帮助编译器:
test "...", { BLOCK };
test("..."){ BLOCK };
test("...")({ BLOCK });
( test "...")({ BLOCK });
但是都不起作用。Perl能否实现我想要的功能?
英文:
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?
答案1
得分: 5
(&) 原型仅在子程序的第一个参数中使用时才具有这种美感。来自 `perldoc perlsub`:
> 有趣的是,"&" 的一件事是,您可以使用它生成新的语法,前提是它在初始位置
提供类似美感水平的一种方法是:
```perl
sub verify ($%) {
my ( $message, %opts ) = @_;
my $coderef = $opts{using};
...;
}
sub using (&) {
my ( $coderef ) = @_;
return ( using => $coderef );
}
# `verify` 子程序接受一个名称,后跟一组选项哈希:
#
verify(
"your message here",
"using" => sub { ... },
);
# `using` 子程序返回一个满足该选项哈希的两元素列表:
#
verify "your message here", using {
...;
};
如果您迫切希望允许类似以下的语法:
verify "description" { boolean-assertion-block };
... 这仍然是可能的,但需要使用黑暗技巧。 Keyword::Simple 可能是您最好的选择,但还有 Devel::Declare 和 Filter::Simple 这些选项。
<details>
<summary>英文:</summary>
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:
```perl
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.
答案2
得分: 4
只有当&
是原型中的第一件事情时,才能使用块语法。来自perlsub:
> &
需要一个匿名子例程,如果作为第一个参数传递,就不需要sub
关键字或后续的逗号。
其他自定义DSL,比如Dancer2或Mojolicious,通常使用sub
关键字。
get '/foo' => sub {
...
};
Plack::Builder和Web::Scraper使用返回对象的块,然后可以嵌套使用。
英文:
You can only use the block syntax if the &
is the first thing in your prototype. From perlsub:
> An &
requires an anonymous subroutine, which, if passed as the first argument, does not require the sub keyword or a subsequent comma
Other custom DSL such as in Dancer2 or Mojolicious typically use the sub
keyword.
get '/foo' => sub {
...
};
Plack::Builder and Web::Scraper use blocks that return objects, which then can be nested.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论