这个 Perl 6 CATCH 块是否应该能够更改词法范围内的变量?
Should this Perl 6 CATCH block be able to change variables in the lexical scope?
我正在玩可恢复的异常。在此示例中,我尝试对不进行数字化的内容进行数字化。我抓住了它并尝试给 $value
变量一个合适的值然后恢复执行:
try {
my $m = 'Hello';
my $value;
$value = +$m;
put "Outside value is 「{$value.^name}」";
CATCH {
when X::Str::Numeric {
put "「$m」 isn't a number!";
put "Inside value is 「{$value.^name}」";
$value = 0;
put "Inside value is now 「$value.」";
.resume;
}
default {
put "Unhandled type 「{.^name}」";
}
}
put "End of the block";
}
put "Got to the end.";
CATCH
块可以看到它所在的词法作用域,从中断处继续。我希望我能够更改 $value
并让块的其余部分使用该值,但在 CATCH
之外,该值变为 Failure:
「Hello」 isn't a number!
Inside value is 「Any」
Inside value is now 「0.」
Outside value is 「Failure」
End of the block
Got to the end.
怎么了?
在 try
块内,use fatal
生效,导致从方法或子调用返回的惰性异常立即抛出。在 try
块的词法范围之外,请注意:
my $value = +$m;
将导致 Failure
被分配给 $value
。 try
将它变成更像的东西:
my $value = force-failure(+$m);
您可以将其定义为:
sub force-failure(Mu \f) { f.sink if f ~~ Failure; f }
(我在挥手,因为编译器吐出代码来内联执行此操作并进行了一些优化)。
在考虑的情况下,.sink
触发了抛出的异常。 CATCH
块运行。 .resume
表示我们不希望像 CATCH
块通常发生的那样展开调用堆栈,因此执行在 force-failure
内部继续,然后 returns f
- Failure
。这一切都发生在主线代码赋值给 $value
之前; Failure
因此被分配,覆盖 CATCH
块给出的值。
不幸的是,您不能使用 //=
来逃避它,因为它会在 运行 RHS 之前进行测试(这是我们通常希望它做的)。但是,可以这样做:
my $numified = +$m;
my $value //= $numified;
当然,这都是一个人为的例子,因为正常的习惯用法是根本没有 try
块,并将其写为:
my $value = +$m // 0;
于是趁势Failure
。通常,可恢复异常需要格外小心,因为在许多情况下,不会编写期望恢复发生的代码。事实证明,为使 Failure
致命而生成的代码就是其中之一。
我正在玩可恢复的异常。在此示例中,我尝试对不进行数字化的内容进行数字化。我抓住了它并尝试给 $value
变量一个合适的值然后恢复执行:
try {
my $m = 'Hello';
my $value;
$value = +$m;
put "Outside value is 「{$value.^name}」";
CATCH {
when X::Str::Numeric {
put "「$m」 isn't a number!";
put "Inside value is 「{$value.^name}」";
$value = 0;
put "Inside value is now 「$value.」";
.resume;
}
default {
put "Unhandled type 「{.^name}」";
}
}
put "End of the block";
}
put "Got to the end.";
CATCH
块可以看到它所在的词法作用域,从中断处继续。我希望我能够更改 $value
并让块的其余部分使用该值,但在 CATCH
之外,该值变为 Failure:
「Hello」 isn't a number!
Inside value is 「Any」
Inside value is now 「0.」
Outside value is 「Failure」
End of the block
Got to the end.
怎么了?
在 try
块内,use fatal
生效,导致从方法或子调用返回的惰性异常立即抛出。在 try
块的词法范围之外,请注意:
my $value = +$m;
将导致 Failure
被分配给 $value
。 try
将它变成更像的东西:
my $value = force-failure(+$m);
您可以将其定义为:
sub force-failure(Mu \f) { f.sink if f ~~ Failure; f }
(我在挥手,因为编译器吐出代码来内联执行此操作并进行了一些优化)。
在考虑的情况下,.sink
触发了抛出的异常。 CATCH
块运行。 .resume
表示我们不希望像 CATCH
块通常发生的那样展开调用堆栈,因此执行在 force-failure
内部继续,然后 returns f
- Failure
。这一切都发生在主线代码赋值给 $value
之前; Failure
因此被分配,覆盖 CATCH
块给出的值。
不幸的是,您不能使用 //=
来逃避它,因为它会在 运行 RHS 之前进行测试(这是我们通常希望它做的)。但是,可以这样做:
my $numified = +$m;
my $value //= $numified;
当然,这都是一个人为的例子,因为正常的习惯用法是根本没有 try
块,并将其写为:
my $value = +$m // 0;
于是趁势Failure
。通常,可恢复异常需要格外小心,因为在许多情况下,不会编写期望恢复发生的代码。事实证明,为使 Failure
致命而生成的代码就是其中之一。