KKK*_*oo0 5 closures smalltalk block
如果我逐个执行它们,以下Smalltalk代码将返回错误"context not not return".有人有解释吗?
f := [ :x :y | ^x + y].
sum:= f value: 3 value: 6.
Run Code Online (Sandbox Code Playgroud)
如果我一次执行它们,它会工作并按9预期返回.
你可能想写
f := [ :x :y | x + y].
sum:=f value: 3 value: 6.
Run Code Online (Sandbox Code Playgroud)
我来告诉你
如果要从方法返回某些内容,可以在方法中使用^插入符来执行此操作:
doSomethingUseful
^ self calculate + 1
Run Code Online (Sandbox Code Playgroud)
这是正常的回报.一切还好.现在输入块.
你总是隐含地从块中返回一些东西,它的最后一个表达式的值.因此,42执行时,此块将返回:
[1 + someObject invert.
anotherObject * 4.
42].
Run Code Online (Sandbox Code Playgroud)
您可以在方法中使用它:
doSomethingUseful: someObject to: anotherObject
| myValue |
myValue := [1 + someObject invert.
anotherObject * 4.
42] value.
^ self calculate + myValue
Run Code Online (Sandbox Code Playgroud)
但是,有时你必须从块中返回函数.一个典型的例子是这样的保护条款:
doThis
self someValueSatisfied ifFalse: [^ self]
self calculate.
^ self someValueComputed.
Run Code Online (Sandbox Code Playgroud)
如果#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.
Run Code Online (Sandbox Code Playgroud)
首先,创建块并将其存储在工作区中的某个位置f.然后这个do-it退出,下一个执行.Smalltalk f在您的工作区中查找,即存储块.它试图执行它并遇到非本地返回.但是,非本地返回仅从定义函数返回,该函数不再执行,因此我们无法从中返回.
当你一次性执行所有事情时,这将是:
DoIt
f := [ :x :y | ^(x+y). ].
sum:=f value: 3 value: 6.
Run Code Online (Sandbox Code Playgroud)
几乎与上面相同,除了现在f执行时,非本地返回可以工作,因为我们仍然在定义块的函数中.所以我们可以从中回来.在这种情况下,非本地返回工作.