whileTrue
什么是从GNU Smalltalk 中不需要返回的循环中断的简单而简洁的方法?
这是我的代码。char_stack
如果为空,我想在第 31 行结束循环。
https://gist.github.com/SYZYGY-DEV333/ea3f5eeb3473927c8faa294bb72a8858
任何帮助将非常感激。
whileTrue
什么是从GNU Smalltalk 中不需要返回的循环中断的简单而简洁的方法?
这是我的代码。char_stack
如果为空,我想在第 31 行结束循环。
https://gist.github.com/SYZYGY-DEV333/ea3f5eeb3473927c8faa294bb72a8858
任何帮助将非常感激。
一般来说,Smalltalk 没有办法从循环中中断,除了从封闭方法返回。
尝试将您的循环提取到另一种方法中,您可以从中返回以从循环中中断。
在某种程度上,Smalltalk 语言甚至没有循环......但有些方法碰巧不止一次地评估块。因此,它没有终止“循环”的特殊方法。回归是一种方式。
如果您还没有这样做,请熟悉一下 Collection 的不同迭代方法:do:
, select:
, collect:
, detect:ifNone:
, ... 后者是在集合上运行“不完整”循环的另一种方法,但它不能解决所有情况您可能希望“休息”。
Peter Deutsch在 Byte 杂志(1982) 上发表的一篇题为“在 Smalltalk-80 系统中构建控制结构”的文章展示了为循环内可能发生的不常见事件实现 while 循环中断是多么容易。
为了实现这一点,我们只需要一个新类和一个对 的扩展BlockClosure
,总共需要9 行代码(!)。
具有两个 ivars和以下方法的类: BlockWithExit
,子类Object
exit
block
on: aBlock
block := aBlock
value
exit := [^nil].
^block value
exit
exit value
扩大
BlockClosure>>withExit
^BlockWithExit new on: self
就是这样!
例子
找到一个集合的最大值,直到它用尽或nil
找到(罕见事件)
maxBeforeNil: aCollection
| max supplier loop |
max := 0.
supplier := aCollection readStream.
loop := [
[supplier atEnd]
whileFalse: [
value := supplier next.
value isNil ifTrue: [loop exit].
max := max max: value]] withExit.
loop value.
^max
为什么它会这样工作?因为具有非本地返回的块从定义该块的方法中退出。
在这种情况下,此方法是BlockWithExit>>value
,因此当[^nil]
从 评估时loop exit
,流退出value
并转到它的发送者,就在 之后loop value
。
Deutsch 发现的突出推论是可以使用在 ivar 中定义退出块的相同技巧来构建整个机制, 例如: .Exceptions
exit := [^nil]