我在玩可恢复的例外。在本例中,我尝试numify一些不numify的东西。我捕捉到这一点,并尝试为$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
之外,该值变为失败:
「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;
将导致故障
分配给$value
。try
将其转换为类似于:
my $value = force-failure(+$m);
你可以想象它被定义为这样的东西:
sub force-failure(Mu \f) { f.sink if f ~~ Failure; f }
(我在挥手,因为编译器吐出代码来内联并进行一些优化)。
在所考虑的情况下,。sink
触发引发的异常。CATCH
块运行。。resume
表示我们不希望像通常在CATCH
块中那样释放调用堆栈,因此在强制失败
内部继续执行,然后返回f
-失败。这一切都发生在主线代码中分配给$value
之前;因此分配了故障
,覆盖了CATCH
块给出的值。
不幸的是,您不能用//=
来逃避这一点,因为它在运行RHS之前进行测试(这是我们通常希望它做的)。但是,可以这样做:
my $numified = +$m;
my $value //= $numified;
当然,这完全是一个人为的例子,因为正常的习惯用法是根本没有一个try
块,并将其写成:
my $value = +$m // 0;
从而利用了Failure
。一般来说,可恢复的异常需要非常小心,因为在许多情况下,代码不会期望发生恢复。事实证明,为使Failure
失效而生成的代码就是这样一段代码。
问题内容: 这将编译 这不会 我希望两者都能编译(也许这是C的工作方式?)。是什么原因导致无法在外部块中以相同的名称声明一个块中的变量? 问题答案: 简短的答案是:因为这是JLS§6.4中定义Java语言的方式。 您可能从其他语言中使用过,因此允许使用所谓的可变阴影。但是,Java语言的发明者认为这是一个笨拙的功能,他们不希望使用其语言: 此限制有助于检测其他一些非常模糊的错误。 但是,正如作者在
问题内容: 我知道变量作用域由块的开始和块的结尾包围。如果在块内声明了相同的变量,则会发生编译错误。但是,请看以下示例。 在这里,可以在方法中重新声明,尽管它已经在类中声明了。但是在块中,无法重新声明。 为什么类范围变量的重新声明不产生错误,而方法范围变量的重新声明却产生错误? 问题答案: 这是因为不是变量,而是实例字段。允许局部变量与字段具有相同的名称。为了区分变量和具有相同名称的字段,我们在实
问题内容: 我知道变量作用域由块的开始和块的结尾包围。如果在块内声明了相同的变量,则会发生编译错误。但是,请看以下示例。 在这里,可以在方法中重新声明,尽管它已经在类中声明了。但是在块中,无法重新声明。 为什么类范围变量的重新声明不产生错误,而方法范围变量的重新声明却产生错误? 问题答案: 这是因为不是变量,而是实例字段。允许局部变量与字段具有相同的名称。为了区分变量和具有相同名称的字段,我们在实
问题内容: 尽管在ChildCtrl中实例化了一个“新”变量,我如何进行变量更改并将其轻松传播回ParentCtrl?加分点数最少,甚至没有$ on和$ watch(使其更易于实现) ParentCtrl ChildCtrl / ChildCtrl2 / ChildCtrl3 / ChildCtrl4 视图 我的ChildCtrl的区别就足够大了,我无法轻松抽象出主布局和ng-view,但是它们都
本章介绍当模板在访问变量时发生了什么事情,还有变量是如何存储的。 当调用 Template.process 方法时,它会在方法内部创建一个 Environment 对象,在 process 返回之前一直使用。 该对象存储模板执行时的运行状态信息。除了这些,它还存储由模板中指令,如 assign, macro, local 或 global 创建的变量。 它不会尝试修改传递给 process 的数据
问题内容: 我有两个控制器,一个封装在另一个中。现在,我知道子范围从父范围继承属性,但是有没有办法更新父范围变量?到目前为止,我还没有遇到任何明显的解决方案。 在我的情况下,我在表单中有一个日历控制器。我想从父范围(即表单)更新开始日期和结束日期,以便表单在提交时具有开始日期和结束日期。 问题答案: 您需要在父作用域中使用一个对象(不是原始对象),然后就可以直接从子作用域中更新它 上级: ctrl