2

我正在尝试自学 Smalltalk。一个教程有这个while循环的例子:

|i| 
i:=5. 
[i >0] whileTrue:[ 
 Transcript show: ((i*2) asString) ; cr. 
 i:=i-1. 
].

据我了解,whileTrue 是发送到 BlockClosure 的消息,告诉接收方 BlockClosure 运行作为参数给出的 BlockClosure,只要接收方为真。

BlockClosure 响应的 whileTrue 消息是如何在 Smalltalk 中没有 while 循环结构的情况下实现的?或者它是用运行时编写的任何语言实现的?

4

3 回答 3

8

在我的 VisualWorks 图像中,它是通过递归完成的:

whileTrue: 一个块

   ^自我价值
      如果真实:
      [aBlock 值。
      [self 值] whileTrue: [aBlock 值]]

但是,还有一个注意事项,如果接收者和参数都是文字块,编译器将内联 #whileTrue: 调用。因此,在大多数情况下,您还可以考虑#whileTrue:一种“神奇”消息,在语法上看起来像消息发送,但实际上已优化为不同的字节码。

于 2009-01-28T23:47:10.037 回答
0

根据这个论坛, whileTrue 不是真正的消息。

于 2009-01-27T22:27:19.497 回答
0

如前所述:编译器在我已知的所有实现中作弊和内联。因此,在正常情况下并不需要该方法存在,并且通常不会调用它。然而,当执行或解释动态生成的代码结构而不实际使用编译器时,该方法可能很有用。

顺便说一句,由于 Smalltalk 语言标准(实际上并不存在)并不强制实现消除尾调用(例如,与 Scheme 相比),VW 中的递归实现对于执行或解释并不是真正有用(除非编译器作弊是标准化的)。

没有递归的替代方法可能是:

whileTrue:aBlock
    self value ifFalse:[^ nil].
    aBlock value.
    thisContext restart
于 2010-08-22T08:20:36.570 回答