我在 Linux Debian 下运行 Perl 脚本版本 5.28,并带有一些实验性的“扩展”,并出现了奇怪的行为。在混合 Pascal-SQL-Perl 编程会话中,我错过了在 if-else 语句中输入小写
begin
而不是 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";
}
/usr/bin/perl "test-if-begin"
BAD: ..running 1000 operations
BAD: ..nothing to do
GOOD: ..running 1000 operations
Do something 1000 times
这是 Perl 的 间接对象表示法 的实际应用。
它允许(推荐的)语法
PackageName->method(args-list)
写成(a“discouraged”)
method PackageName arg-list
让我们将示例程序归结为
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"
}
}
通过间接对象语法,子内部的代码相当于
do {
print "This body stands for package name\n";
return
} -> anyword;
这是合法的语法,在运行时,
return
语句是“保存”它的,因为它永远不会达到不存在的anyword
。
如果我们放弃
return
indirect_notation_gotcha();
print "all good?\n";
sub indirect_notation_gotcha {
anyword {
print "This body stands for package name\n";
}
}
现在
anyword
is 已尝试,我们得到
这个body代表包名 无法通过包“1”找到对象方法“anyword”(也许您忘记加载“1”?)在...
直接相关
也直接相关,更复杂且有一些变化
在许多情况下,通过使用 O 和
Deparse
后端,可以看到解释器如何处理给定的代码,例如
perl -MO=Deparse script.pl
但是,对于更复杂的代码,这可能不起作用,如上面的第二个示例
如顶部链接所示,在较新的 Perls 中,这是一个可以禁用的功能(使用 v5.32+)
feature qw(indirect); # v5.32+
在较新的 Perls 中,它在捆绑包中被禁用,
use v5.36;
请参阅 perldelta 5.36.0。