views:

348

answers:

3

I am trying to teach myself Smalltalk. A tutorial has this example of a while loop:

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

As I understand it, whileTrue is a message sent to a BlockClosure, telling the receiving BlockClosure to run the BlockClosure given as the argument as long as the receiver is true.

How is the whileTrue message that BlockClosure responds to implemented without a while loop construct in Smalltalk? Or is it implemented in whatever language the run-time is written in?

A: 

According to this forum whileTrue is not a real message.

jmihalicza
The implementation as if it was a real message has to exist, because you can do "aClosure perform: #whileTrue", which will indeed use the normal message dispatch and end up in the code as written there. But the nice thing is that the then-triggered code uses the "magical" definition properly.
Randal Schwartz
+5  A: 

In my VisualWorks image, it's done with recursion:

whileTrue: aBlock

   ^self value
      ifTrue:
      [aBlock value.
      [self value] whileTrue: [aBlock value]]

However, there's also a note to the effect that the compiler will inline a #whileTrue: call if both the receiver and argument are literal blocks. So in most cases, you can also consider #whileTrue: one of the "magic" messages that looks like a message send syntactically, but is really optimized into different bytecodes under the hood.

Ash Wilson
I thought it might have something to do with recursion, but I was skeptical that a seemingly fundamental "construct" was implemented in a potentially costly way.
moffdub
The compiler has to cheat for a few methods like that; in practice it's not a problem because you never need to redefine such basic methods. It's a bit like The Truman Show, the sun is actually a projector because the budget didn't allow for an actual star :)
Damien Pollet
A: 

As already mentioned: the compiler cheats and inlines in all implementations known to me. So there is not really a need for the method to be present in normal situations and it is usually not invoked. The method might be useful however, when performing or interpreting dynamically generated code-structures without actually using the compiler.

By the way, as the Smalltalk language standard (which does not really exist) does not force implementations to be tail-call-eliminating (in contrast to Scheme, for example), the recursive implementation in VW is not really useful for performing or interpretation (unless the compiler-cheat is standardized).

An alternative without recursion could be:

whileTrue:aBlock
    self value ifFalse:[^ nil].
    aBlock value.
    thisContext restart
blabla999