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

Smalltalk 如果进程终止,是否可以执行整个确保块?,smalltalk,pharo,Smalltalk,Pharo,今天,我了解到,在法罗执行: [v := 1] ensure: [self halt. v := 2] 将结束设置v=2,即使我们在halt窗口(!)放弃该过程 我认为这是有争议的。对我来说,#sure:的语义意味着序列 self halt. v := 2 必须执行,无论接收器块的情况如何,而不管参数块的逻辑如何。由于#halt的逻辑包含终止过程的事件,我发现它干扰了对第二句的顽固评估 接下来,我尝试了以下方法: [v := 1] ensure: [1 / 0. v := 2] 当出现Ze

今天,我了解到,在法罗执行:

[v := 1] ensure: [self halt. v := 2]
将结束设置
v=2,
即使我们在
halt
窗口(!)放弃该过程

我认为这是有争议的。对我来说,
#sure:
的语义意味着序列

self halt. v := 2
必须执行,无论接收器块的情况如何,而不管参数块的逻辑如何。由于
#halt
的逻辑包含终止过程的事件,我发现它干扰了对第二句的顽固评估

接下来,我尝试了以下方法:

[v := 1] ensure: [1 / 0. v := 2]
当出现
ZeroDivide
异常时,我关闭了调试器,
v
的值仍然是
2
(与
#halt
相同)

最后,我评估:

[v := 1] ensure: [n := 1 / 0. v := v + n]
并在
零除法
异常上关闭调试器。这次
v
的值是
1
,但我没有例外,因为
v+n
无法计算。换言之,错误一直在悄无声息地继续


所以我的问题是。这种行为背后的理性是什么?该过程是否应该在“正常”情况下终止,即没有
#确保:
参与时终止?

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


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

我想这是任何(ANSI)标准都没有完全定义的行为,如果我错了,请纠正我

其他的小对话似乎表现不同。我在Smalltalk/X中尝试过,调试器提供了3个选项:“继续”(即继续)、“中止”(即展开)和“终止”(即终止进程)。我猜“终止”对应于Squeak在关闭调试器时所做的操作

使用“中止”和“终止”,确保块的其余部分不执行,使用“继续”则执行。我想这没关系,你也会这么想的

在Abort和Terminate(这两个异常处理程序都是对应的异常处理程序的展开)时,它不应该尝试重新评估或继续执行可能错误/错误/失败的块

如果要继续或不继续,则由处理程序(调试器基本上就是这样)选择。如果没有,那么它应该退出sure块并继续执行调用链中可能在上面的任何其他sure块

这与异常处理块的行为一致,如果在中引发相同的异常,也不会重新评估或处理异常块。在ST/X中,异常类中有显式代码来处理这种情况,因此它肯定是出于目的而不是副作用


我猜这在Squeak中是错误的,应该告诉Squeak开发者。

我在pharo开发者邮件列表中没有看到你的问题。在那里(以及在吱吱作响的地方)比在其他地方更合适here@StephanEggermont:事实上,它在邮件列表中也是合适的,但这并不意味着它在这里不合适。在我看来,太多的知识在那些邮件列表中丢失了。。。他们不是每个人都喜欢的@StephanEggermont:这很公平,但是Leandro或其他任何人都无法知道他遇到的问题是否需要进行“设计权衡讨论”,当他遇到不容易立即解释的事情时。嘿@Amos,我们正在谈论的是Leandro。他知道:)不过你说得有道理。@StephanEggermont你的反对“技术上”是对的(@amoscarcenter也是!)。但Smalltalk需要出现在StackOverflow这样的开放论坛上,因为我们需要更多的可见性。