Perl`*foo {THING}`,subs和括号

Dac*_*cav 3 perl

除了经典的函数调用

sub foo { ... };
foo 1, 2, 3;
Run Code Online (Sandbox Code Playgroud)

Perl允许定义闭包

my $foo = sub { ... };
$foo->(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,词汇本地)

即使我找不到它的非hackish目的,Perl也允许这样做:

*main::foo = sub { ... }
Run Code Online (Sandbox Code Playgroud)

它获得与第一种形式几乎相同的效果,除了我必须在参数周围加上括号:

foo(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)

如果我没有括号,我会收到以下错误:

Number found where operator expected at - line 6, near "&main::foo 1"
    (Missing operator before  1?)
syntax error at - line 6, near "main::foo 1"
Execution of - aborted due to compilation errors.
Run Code Online (Sandbox Code Playgroud)

...如果我用&foo 1, 2, 3语法调用它,也会发生这种情况,并明确表示它是关于函数的.

所以我的问题是:

  • 为什么括号可以在第一种形式中省略,而不是在第三种形式中省略?

  • 第三种形式有目的吗?在我看来,在一个包的命名空间中注入一个回调是一种不好的做法,因为它会使事情变得隐含且无法检测到.

谢谢你的回答.

cho*_*oba 8

*main::foo = sub {在运行时进行评估,而在编译时抛出错误.sub在编译时解析Normal ,然后Perl解析器可以将其名称识别为裸字,但在声明之前仍然无法使用裸字形式:

foo 1;  # Number found where operator expected...
sub foo {
    say shift;
}
foo 1; # No error here.
Run Code Online (Sandbox Code Playgroud)

您可以通过将代码封装到BEGIN块中来将代码安排到编译时:

BEGIN {
    *main::foo = sub { say shift };
}
foo 1; # No error!
Run Code Online (Sandbox Code Playgroud)

  • @Dacav:在某些情况下使用符号表可能很有用 - 生成getter/setter,mocking等. (2认同)