小写“begin”是 Perl 关键字吗?

huc*_*inn 3 perl keyword

我在 Linux Debian 下运行 Perl 脚本版本 5.28,并带有一些实验性的“扩展”,并出现了奇怪的行为。在混合 Pascal-SQL-Perl 编程会话中,我错过了在 if-else 语句中输入小写字母begin而不是 an else(请参阅下面的测试代码),并得到了有效但出现故障的代码。

我知道大写BEGIN关键字属于BEGIN, UNITCHECK, CHECK, INIT and END程序“程序运行前和程序运行后”组。但我使用了小写begin变体,并且得到了有效的运行代码。在我看来,该begin {...}块是在if (...) {...}表达式之后单独执行的,这会导致不必要的提前返回。

小写字母begin在 Perl 区分大小写的编程上下文中有任何意义吗?

#!/usr/bin/perl
use v5.20;
use strict;
use warnings;
use feature qw(signatures);
no warnings 'once';
no warnings 'experimental';
no warnings 'experimental::signatures';

&if_exotic(1000);
&if_normal(1000);

# --------------------------------------
# Bad variant
# --------------------------------------
sub if_exotic($want) {

   if ($want>0) {
       print "BAD: ..running $want operations\n";
   } begin {
       print "BAD: ..nothing to do\n";
       return;
   }

    print "Do something $want times\n";
   
}

# --------------------------------------
# Good variant
# --------------------------------------
sub if_normal($want) {

   if ($want>0) {
       print "GOOD: ..running $want operations\n";
   } else {
       print "GOOD: ..nothing to do\n";
       return;
   }

    print "Do something $want times\n";
}

Run Code Online (Sandbox Code Playgroud)
/usr/bin/perl "test-if-begin"
BAD: ..running 1000 operations
BAD: ..nothing to do
GOOD: ..running 1000 operations
Do something 1000 times
Run Code Online (Sandbox Code Playgroud)

zdi*_*dim 9

这是 Perl 的间接对象表示法的实际应用。

它允许(推荐)语法

PackageName->method(args-list)
Run Code Online (Sandbox Code Playgroud)

写成(“气馁”)

method PackageName arg-list
Run Code Online (Sandbox Code Playgroud)

让我们将示例程序归结为

use warnings;
use strict;

indirect_notation_gotcha();

print "all good?\n";

sub indirect_notation_gotcha {

    anyword {
        print "This body stands for package name\n";
        return;                                      # runs before "anyword"
    }

}
Run Code Online (Sandbox Code Playgroud)

通过间接对象语法,子内部的代码相当于

do {
    print "This body stands for package name\n";
    return
} -> anyword;
Run Code Online (Sandbox Code Playgroud)

这是合法的语法,在运行时,该return语句是“保存”它的,因为它永远不会到达不存在的anyword.

如果我们放弃return

indirect_notation_gotcha();

print "all good?\n";

sub indirect_notation_gotcha {
    anyword {
        print "This body stands for package name\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

现在anyword 尝试,我们得到

这个body代表包名
无法通过包“1”找到对象方法“anyword”(也许您忘记加载“1”?)在...

如顶部链接所示,在较新的 Perls 中,这是一个可以禁用的功能(使用v5.32+

 no feature qw(indirect);  # v5.32+
Run Code Online (Sandbox Code Playgroud)

在较新的 Perls 中,它也在捆绑包中被禁用

use v5.36; 
Run Code Online (Sandbox Code Playgroud)

请参阅5.36.0 的 perldelta