Newsgroups: comp.lang.smalltalk
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!howland.reston.ans.net!news.sprintlink.net!EU.net!uunet!world!jhaungs
From: jhaungs@world.std.com (Jim Haungs)
Subject: Re: whileTrue:
Message-ID: <Cyp3xq.7GG@world.std.com>
Organization: The World Public Access UNIX, Brookline, MA
References: <9411022316.AA04248@sci.brooklyn.cuny.edu>
Date: Thu, 3 Nov 1994 14:22:37 GMT
Lines: 65

Gerald Weiss 718-951-5945 <weiss@SCI.BROOKLYN.CUNY.EDU> writes:

>I'm sure I'm being dense, but could someone explain the following
>implementation of whileTrue: from GNU Smalltalk? Isn't the embedded
>whileTrue: message simply a recursive one, and if so, where is the
>escape clause?

>The way I read it, the second function (using the unary selector whileTrue)
>is a syntactic convenience, not an escape clause for the whileTrue:



>!BlockContext methodsFor: 'basic'!

>whileTrue: aBlock
>    [ self value ] whileTrue: [ aBlock value ].
>    ^nil
>!

>whileTrue
>    ^[ self value ] whileTrue: []
>!

>!!

This is one of those places in Smalltalk where, as Peter Deutsch says, 
"In Smalltalk, you must cheat; but you must also not get caught."

The compiler inlines most boolean control messages into real
forward and backward virtual machine branches.  In most Smalltalk
compilers, this is done only for literal blocks, since a block in a
variable cannot statically be guaranteed to BE a block.

Thus,
	[true] whileTrue: [self doSomething] 

is compiled into:

	Label: self doSomething
		branchBackwardTo: Label

But, 
	aBlock := [true].
	aBlock whileTrue: [self doSomething]

actually calls the whileTrue: method in BlockClosure (or wherever).
However, in the whileTrue and whileTrue: methods, the [self value] in 
block brackets allows the inlining of the whileTrue: message, 
thus eliminating the recursion.

The following comment is from BlockClosure>>whileTrue: in 
ParcPlace's VisualWorks:

"This method is inlined if both the receiver and the argument are literal
blocks. In all other cases, the code above is run. Note that the code
above is defined recursively. However, to avoid actually building an
activation record each time this method is invoked recursively, we have
used the '[...] whileTrue: [..]' form in the last line, rather than the more
concise 'self whileTrue: aBlock'. Using literal blocks for both the receiver
and the argument allows the compiler to inline #whileTrue:, which (in the
absence of type inferencing) could not be done if we were to use
'self whileTrue: aBlock'."

Hope this is helpful.
Jim
