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