Who wants full block closures and why?

David N. Smith (IBM) dnsmith at watson.ibm.com
Sat Jul 17 19:54:59 UTC 1999


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.

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.)

Because blocks that are not closures are ugly kludges.

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.

Closures allow implementation of recursive blocks, and, yes indeed, 
they are useful. Beside, why should the worlds best language have 
such an ugly restriction?

Because, these days, it's not Smalltalk unless it has closures. (I 
guess I must feel strongly about this!  :-)

(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!)


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!)

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?

Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.





More information about the Squeak-dev mailing list