On Mon, Aug 16, 2010 at 11:28 AM, Randal L. Schwartz
<[email protected]>wrote:

> >>>>> "Hernan" == Hernan Wilkinson <[email protected]> writes:
>
>
> Hernan> whileTrue: aBlock
>
> Hernan>    self value ifTrue: [
> Hernan> aBlock value.
> Hernan> thisContext restart ]
>
> That's an interesting implementation, but the current implementation
> is clean, and is there only because #perform: has to be able to do it.
>

Forgive me for being so blunt but IMO the current implementation is a crok.
 It can't possibly work in the absence of the inlining optimization in
MessageNode:
whileTrue: aBlock
"Ordinarily compiled in-line, and therefore not overridable.
This is in case the message is sent to other than a literal block.
Evaluate the argument, aBlock, as long as the value of the receiver is
true."

^ [self value] whileTrue: [aBlock value]

I stupidly forgot to change it in BlockClosure.  The following /can/ work
without inlining (and can work as well as the inlined version if the
compiler implements tail-recursion elimination):

whileTrue: aBlock
"Ordinarily compiled in-line, and therefore not overridable.
This is in case the message is sent to other than a literal block.
Evaluate the argument, aBlock, as long as the value of the receiver is
true."

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

BTW here's the VisualWorks 7.7 method.  For me it's a little too clever.

whileFalse: aBlock
"Evaluate the argument, aBlock, as long as the value of the receiver is
false."

^self value
ifFalse:
[aBlock value.
[self value] whileFalse: [aBlock value]]

"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 '[...] whileFalse: [..]' form in the last line, rather than the
more
concise 'self whileFalse: aBlock'. Using literal blocks for both the
receiver
and the argument allows the compiler to inline #whileFalse:, which (in the
absence of type inferencing) could not be done if we were to use
'self whileFalse: aBlock'."

but it's accurate and does the job of turning
    | a b |
    a := [i <= j].
    b := [i := i + 1].
    a whileTrue: b
into an iterative execution.

So at the very least we should improve the comment in whileTrue: and
whileFalse: to point to the compiler optimization in MessageNode and IMO the
VisualWorks implementation is the best compromise between clarity and
honesty given the lack of tail-recursion elimination.

2ยข

best,
Eliot



> Maybe this definition could be added as a comment to the method though,
> to show how you would do it *if* it wasn't inlined.


> --
> Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
> <[email protected]> <URL:http://www.stonehenge.com/merlyn/>
> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
> See http://methodsandmessages.vox.com/ for Smalltalk and Seaside
> discussion
>
> _______________________________________________
> Pharo-project mailing list
> [email protected]
> http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project
>
_______________________________________________
Pharo-project mailing list
[email protected]
http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project

Reply via email to