这是由于间接对象语法造成的,并且是 this example 的更精细的变体。
"indirect object notation" 允许代码
PackageName->method(@args);
写成
method PackageName @args;
所以“try”和“catch”这两个词无关紧要。这里有趣的一点是更多的涉及和扩展的语法,有两个部分,每个部分都使用这种间接对象表示法。
有问题的代码实际上具有method BLOCK LIST 形式,但这也通过间接对象语法进入(do BLOCK)->method(LIST),其中do BLOCK 需要生成包的名称或祝福(对象)引用以获得有意义的方法调用。这在下面的Deparse 输出中可以看到。
在此代码上使用B::Deparse 编译器后端(通过O 模块)
use strict;
use warnings;
use feature 'say';
try { call_a( 'x' ) }
catch {
die "ACTUALLY die";
#say "NO DONT die";
};
sub call_a {
die "Yes it dies";
#say "no die";
}
perl -MO=Deparse script.pl 应该显示非常接近的近似值:
使用警告;
使用严格;
使用功能“说”;
尝试 {
call_a('x')
} 做 {
死'实际上死'
}->捕捉;
子调用_a {
使用警告;
使用严格;
使用功能“说”;
die '是的,它死了';
}
undef_sub.pl 语法OK
对于Deparse 而言,嵌套的间接对象语法显然太多了,它仍然在输出中留下method BLOCK LIST 形式。等价的代码可以写成
(do { call_a('x') })->try( (do { die("ACTUALLY die") })->catch() );
在这种情况下更简单
call_a('x')->try( die("ACTUALLY die")->catch() );
因此,原始代码被解释为有效语法 (!),它是 try (call_a('x')) 之后块的内容首先运行 --- 所以程序死了,然后永远不会去追求“方法”try。
如果我们把例子改成
会更有趣
use strict;
use warnings;
use feature 'say';
try { call_a( 'x' ) }
catch {
#die "ACTUALLY die";
say "NO DONT die";
};
sub call_a {
#die "Yes it dies";
say "no die";
}
在任何地方都没有die-ing。用-MO=Deparse运行看看
use warnings;
use strict;
use feature 'say';
try {
call_a('x')
} (catch {
say 'NO DONT die'
} );
sub call_a {
use warnings;
use strict;
use feature 'say';
say 'no die';
}
undef_sub.pl syntax OK
现在是直接的method {} args 语法(args 本身也由Deparse 以间接对象表示法显示)。
等效代码是
call_a('x')->try( say("NO DONT die")->catch() );
首先call_a() 去哪里,在它返回之后,接下来运行try 方法调用中的参数列表的代码。我们没有遇到die,实际运行情况如下
不死
不,不要死
不能在没有包或对象引用的情况下调用方法“catch”...
所以现在方法“catch”确实出现了问题。
感谢ikegami cmets
如果上面的块要返回一个确实有方法catch的包(或对象引用)的名称,那么最终也会尝试try
use strict;
use warnings;
use feature 'say';
BEGIN {
package Catch;
sub catch { say "In ", (caller(0))[3] };
$INC{"Catch.pm"} = 1;
};
use Catch;
try { call_a( 'x' ) }
catch {
say "NO DONT die";
"Catch";
};
sub call_a { say "no die" }
现在我们有了等价物
call_a('x')->try( do { say("NO DONT die"); 'Catch' }->catch() );
输出
不死
不,不要死
在 Catch::catch 中
无法在 undef_sub.pl 第 14 行调用没有包或对象引用的方法“try”。