Who wants full block closures and why?
Jarvis, Robert P.
Jarvisb at timken.com
Mon Jul 19 18:36:56 UTC 1999
OK, so inner classes are an even uglier kluge. Full closures are still more
elegant.
Bob Jarvis
The Timken Company
> -----Original Message-----
> From: Alan Lovejoy [SMTP:sourcery at pacbell.net]
> Sent: Saturday, July 17, 1999 8:20 PM
> To: David N. Smith (IBM); squeak at cs.uiuc.edu
> Subject: re: Re: Who wants full block closures and why?
>
> > ** Original Sender: "David N. Smith \(IBM\)" <dnsmith at watson.ibm.com>
> > At 16:29 -0700 7/15/99, Craig Latta wrote:
> > > I'm compiling a summary for spec/documentation purposes. (I
> > >also intend to implement them :)
> >
> > I do! Why?
> >
> > Because I use them all the time in other implementations.
>
> Yes. So do I.
>
> > Because they allow optimized blocks: you can declare local variables
> > inside the block, not reference anything outside the block, and not
> > have to save a context. (And even if you *do* save the context you
> > don't have problems with multiple blocks referencing the same local
> > variable.)
>
> This does not require closure semantics. It just requires that blocks
> have naming scopes and activation frames independent of the ones for
> the containing method.
>
> > Because blocks that are not closures are ugly kludges.
>
> Yeah, but these things are relative. Squeak's blocks are elegant compared
> to, say, Java inner classes :-).
>
> > Because you can pass optimized closures here and there and everywhere
> > else and hot have to worry about conflicts with single copy local
> > variables in the context.
>
> Yes.
>
> > Closures allow implementation of recursive blocks, and, yes indeed,
> > they are useful. Beside, why should the worlds best language have
> > such an ugly restriction?
>
> Again, recursion only requires that each execution of a block have
> a separate activation frame (e.g. in Smalltalk lingo, a separate Context).
>
>
> > Because, these days, it's not Smalltalk unless it has closures. (I
> > guess I must feel strongly about this! :-)
>
> Yes. We're getting ANSI for closures! :-).
>
> > (As a non-implementer, maybe I'm giving closures properties that are
> > not properly due to closures, but to other problems with blocks;
> > regardless, they are broken!)
>
> Yes. Yes. Yes.
>
> > Non-cute example:
> >
> > | blockArray dataArray |
> > blockArray := Array new: 5.
> > dataArray := #( 'Apple' 'Orange' 'Grape' 'Lemon' 'Kiwi').
> > 1 to: blockArray size do: [ :index |
> > blockArray
> > at: index
> > put: [ dataArray at: index ] ].
> > ^ (blockArray at: 2) value
> >
> > In Squeak 2.4c it gets an index out of range error. (Yes, indeed! See
> > if you can figure out why before running it!)
>
> Because the value of index (whose storage scope is that of the containing
> method)
> will be 6 when the block "[dataArray at: index]" actually executes. This
> highlights
> the semantic non-symmetry created by blocks that are not closures: unlike
> methods,
> their arguments and temporaray variables do not have a storage location
> that differs
> with each execution.
>
> > Interesting to note that VW 2.5 (my most recent version) answers
> > 'Orange', while IBM/ST 4.5 answers 'Kiwi'.
> >
> > There seems to be some disagreement about when variables in a context
> > are bound to the block. While 'Orange' is the answer I intended, I
> > find the IBM/ST result more understandable since there is no tricky
> > binding. (But, maybe I'm just confused!) To get an answer of 'Orange'
> > in IBM/ST it is necessary to write the #at:put: this way:
> >
> > | blockArray dataArray |
> > blockArray := Array new: 5.
> > dataArray := #( 'Apple' 'Orange' 'Grape' 'Lemon' 'Kiwi').
> > 1 to: blockArray size do: [ :index |
> > blockArray
> > at: index
> > put: ([ :n |
> > [ dataArray at: n ]
> > ] value: index) ].
> > ^ (blockArray at: 2) value
> >
> > At the time the #at:put: is executed, a block is evaluated, passing
> > index, and answering another block which has the value of index, but
> > not a direct reference to index.
> >
> >
> > I don't particularity care which way it works, provided that there
> > are simple rules that describe it, and so that one is not terribly
> > surprised by the results. I find the VW result confusing after some
> > thought since it appears to reference a local variable, but doesn't;
> > I find the IBM/ST code less than obvious at first, but quite clear
> > once I've thought about it a while.
> >
> > So, how should it be?
>
> The VA behavior implies that it interprets block arguments (and perhaps
> also temporaries?) as what C would call "static variables". That is,
> different executions of the same block all share the same storage
> location for these variables. Your second example works by defining
> a new block for each loop of the outer block, thus defining a new
> activation
> frame. The outer block only has one activation frame, because it is
> only defined once (apparently, each invocation of the containing context
> defines a new activation frame for the block).
>
> The VA semantics does not satisfy the formal definition of closure. It
> also makes the semantics of code depend on whether it is encapsulated
> as a block or a method (methods don't have "static" variables).
>
> I vote for real closures.
>
> --Alan
>
>
>
> Download Neoplanet at http://www.neoplanet.com
More information about the Squeak-dev
mailing list
|