GNU Smalltalk - 在没有 return 的情况下从 whileTrue 循环中断
GNU Smalltalk - Break from whileTrue loop without return
在 GNU Smalltalk 中从不需要返回的 whileTrue
循环中断的简单明了的方法是什么?
这是我的代码。如果 char_stack
为空,我想在最后的第 31 行中断循环。
https://gist.github.com/SYZYGY-DEV333/ea3f5eeb3473927c8faa294bb72a8858
如有任何帮助,我们将不胜感激。
一般来说,Smalltalk 没有办法从循环中中断,除了 return 从封闭方法中断。
尝试将循环提取到另一个方法中,您可以从中return 中断循环。
在某种程度上,Smalltalk 语言甚至没有循环......但有些方法碰巧不止一次地评估块。因此它没有特殊的方式来终止 "loops"。 Return 就是这样。
如果您还没有这样做,请熟悉 Collection 的不同迭代方法:do:
、select:
、collect:
、detect:ifNone:
、...后者是 运行 对集合进行 "incomplete" 循环的另一种方法,但它并不能解决您可能希望 "break".
的所有情况
其中一篇 articles of the Byte magazine (1982) 在 Smalltalk-80 系统中构建控制结构 Peter Deutsch,显示了为循环内可能发生的 偶发事件 实施 while 循环中断是多么容易。
要实现这一点,我们只需要一个新的 class 和对 BlockClosure
的扩展,总共 9 行代码 (!)。
class:BlockWithExit
,Object
的子class 有两个 ivars 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
为什么这样工作?因为一个非局部的块return从定义该块的方法中退出.
在这种情况下,此方法是 BlockWithExit>>value
,因此当从 loop exit
评估 [^nil]
时,流程退出 value
并转到其发送者,紧接着 loop value
.
Deutsch 发现的突出推论是 Exceptions
的整个机制都可以使用同样的技巧构建 在 ivar 中定义一个退出块,例如:exit := [^nil]
.
在 GNU Smalltalk 中从不需要返回的 whileTrue
循环中断的简单明了的方法是什么?
这是我的代码。如果 char_stack
为空,我想在最后的第 31 行中断循环。
https://gist.github.com/SYZYGY-DEV333/ea3f5eeb3473927c8faa294bb72a8858
如有任何帮助,我们将不胜感激。
一般来说,Smalltalk 没有办法从循环中中断,除了 return 从封闭方法中断。
尝试将循环提取到另一个方法中,您可以从中return 中断循环。
在某种程度上,Smalltalk 语言甚至没有循环......但有些方法碰巧不止一次地评估块。因此它没有特殊的方式来终止 "loops"。 Return 就是这样。
如果您还没有这样做,请熟悉 Collection 的不同迭代方法:do:
、select:
、collect:
、detect:ifNone:
、...后者是 运行 对集合进行 "incomplete" 循环的另一种方法,但它并不能解决您可能希望 "break".
其中一篇 articles of the Byte magazine (1982) 在 Smalltalk-80 系统中构建控制结构 Peter Deutsch,显示了为循环内可能发生的 偶发事件 实施 while 循环中断是多么容易。
要实现这一点,我们只需要一个新的 class 和对 BlockClosure
的扩展,总共 9 行代码 (!)。
class:BlockWithExit
,Object
的子class 有两个 ivars 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
为什么这样工作?因为一个非局部的块return从定义该块的方法中退出.
在这种情况下,此方法是 BlockWithExit>>value
,因此当从 loop exit
评估 [^nil]
时,流程退出 value
并转到其发送者,紧接着 loop value
.
Deutsch 发现的突出推论是 Exceptions
的整个机制都可以使用同样的技巧构建 在 ivar 中定义一个退出块,例如:exit := [^nil]
.