smalltalk块 - 我可以显式设置返回值并停止执行块吗?

mil*_*lan 3 smalltalk block

#value:message的返回值,当发送到块时,是该块中最后一个句子的值.所以[ 1 + 2. 3 + 4. ] value评估为7.我发现有时难以使用.有没有办法显式设置返回值并停止执行块?

对于练习,尝试重写此块而不使用我想象的#return:消息,看看它有多难看.我肯定错过了什么.

[ :one :two |
  one isNil ifTrue: [ two isNil ifTrue: [ self return: nil ] ifFalse: [ self return: true ] ].
  two ifNil: [ self return: false ].

 (one > two)
  ifTrue: [ self return: true ]
  ifFalse: [ (one < two)
              ifTrue: [ self return: false ]
              ifFalse: [ self return: nil ]
            ].
]
Run Code Online (Sandbox Code Playgroud)

编辑:self return: sth真的是胡说八道,但它确实在某种程度上有意义:)

Fra*_*rar 7

没有什么比一个保护子句 - blah ifTrue: [^ foo]在一个块内部,因为^是一个非本地返回,从调用块而不是块本身的方法返回.

大块 - 就像大块头一样 - 应该被重构为更小,更易理解/易处理的子部分,但有时候这并不总是可能的.我的意思是这个答案提出了一些建议选项,当你无法以通常的方式进行简化时.

如果您的块实际上非常复杂,并且您无法将其简化(例如,将其拆分为太多本地信息),那么您可以使用显式返回值.特别是,如果您的区块没有返回,nil您可以执行类似的操作

[:one :two | | result |
    result := (one isNil and: [two isNil]) ifTrue: [false].
    result ifNil: ["do one thing, possibly setting result"].
    result]
Run Code Online (Sandbox Code Playgroud)

如果你的块可以返回nil,你将需要另一个sentinel值:

[:one :two | | result marker |
    result := marker := Object new.
    (result == marker) ifTrue: ["do one thing, possibly setting result"].
    result]
Run Code Online (Sandbox Code Playgroud)

最后 - 我犹豫建议 - 你可以这样做:

[1 + 2.
thisContext return: 5.
3 + 4] value
Run Code Online (Sandbox Code Playgroud)

返回5.

(验证它如何与作为读者练习的左侧^选择器和内联选择器进行交互#ifTrue:ifFalse:.)