以下Smalltalk代码返回错误"上下文无法返回"如果我一个接一个地执行它们。有人有解释吗?
f := [ :x :y | ^x + y].
sum:= f value: 3 value: 6.
如果我一次执行它们,它会起作用并按预期返回9
。
答案 0 :(得分:8)
你可能想写
f := [ :x :y | x + y].
sum:=f value: 3 value: 6.
让我告诉你一下
如果要从方法中返回某些内容,可以在方法中使用^
插入符来执行此操作:
doSomethingUseful
^ self calculate + 1
这是正常的回报。一切还好。现在输入块。
你总是隐式地从块中返回一些东西,即它的最后一个表达式的值。
因此,执行时,此块将返回42
:
[1 + someObject invert.
anotherObject * 4.
42].
您可以在方法中使用它:
doSomethingUseful: someObject to: anotherObject
| myValue |
myValue := [1 + someObject invert.
anotherObject * 4.
42] value.
^ self calculate + myValue
但是,有时您必须从函数中退出。 一个典型的例子是 guard子句,如下所示:
doThis
self someValueSatisfied ifFalse: [^ self]
self calculate.
^ self someValueComputed.
如果#someValueSatsified
返回false
,则该方法会立即返回,并且永远不会执行#calculate
或#someValueComputed
。此效果称为非本地返回,因为您从块而不是返回到其调用上下文(这将是本地),但形成了它定义的方法(! )。
这是由于处理“Do-it”的方式,例如。吱吱声或Pharo。当您按下Ctrl-D(或等效的)时,当前选择的代码被秘密编译为一种方法(好吧,发生了一点点,但让我们忽略它)。如果执行1 halt
并查看调试器,则可以看到。
因此,按行执行代码将执行以下操作:
DoIt
f := [ :x :y | ^(x+y). ]. "! f is now defined in the work space"
DoIt
sum:=f value: 3 value: 6.
首先,创建块并将其存储在工作区中的某个位置f
。然后这个do-it退出,下一个执行。 Smalltalk在您的工作区中找到f
,即存储的块。它试图执行它并遇到非本地返回。但是,非本地返回仅从定义函数返回,该函数不再执行,因此我们无法从中返回。
当您一次性执行所有操作时,这将是:
DoIt
f := [ :x :y | ^(x+y). ].
sum:=f value: 3 value: 6.
与上面的几乎相同,除了现在执行f
时,非本地返回可以工作,因为我们仍然在函数中定义了块。所以我们可以从中回来。在这种情况下,非本地返回工作。