如果进程终止,是否可以执行整个ensure块?

Lea*_*lia 5 smalltalk pharo

今天我在Pharo中了解到执行:

[v := 1] ensure: [self halt. v := 2]
Run Code Online (Sandbox Code Playgroud)

v = 2,即使我们在halt窗口放弃过程(!),也会结束设置.

我发现这个值得商榷.对我来说,语义#ensure:意味着序列

self halt. v := 2
Run Code Online (Sandbox Code Playgroud)

必须执行,无论接收器块的情况如何,都不管参数块的逻辑如何.由于逻辑#halt包括终止过程的事件,我发现它对第二句的顽固评价具有侵扰性.

接下来我尝试了以下内容:

[v := 1] ensure: [1 / 0. v := 2]
Run Code Online (Sandbox Code Playgroud)

ZeroDivide异常弹起我关上了调试器,仍然值v2(同用#halt.)

最后,我评估了:

[v := 1] ensure: [n := 1 / 0. v := v + n]
Run Code Online (Sandbox Code Playgroud)

并在ZeroDivide异常上关闭调试器.这次的价值v是,1但我v + n无法评估无法评估的事实.换句话说,错误继续无声.

所以我的问题是.这种行为背后的理性是什么?该过程是否应该在"正常"情况下终止,即没有#ensure:涉及?

Amo*_*ter 4

有趣的一个。看来您的答案在于方法BlockClosure>>valueNoContextSwitch,该方法被调用#ensure:。如果您阅读那里的注释,它会说它创建了(在原语中)的精确副本,并且返回该副本的返回值,而不是包含您终止的BlockClosure>>value原始块的返回值。因此,即使原始halt文件没有完成,副本也会被执行(显然忽略了复制的文件)。halt

我的猜测是,这是为了确保(没有双关语)该ensure:块始终运行,但会产生忽略原始块终止的意外副作用。我同意你的观点,这不仅违反直觉,而且可能不是我们想要的。