Block Closures

Avi Bryant avi at beta4.com
Wed Feb 25 05:13:59 UTC 2004


On Feb 24, 2004, at 8:30 PM, Aaron Lanterman wrote:

>
> Would it be correct to say that Smalltalk blocks are analogous to 
> Lisp's
> lambda expressions, and that they act like Scheme blocks (lexical 
> scoping)
> as opposed to Emacs Lisp blocks (dynamic scoping)?

Yes, but.

Currently Squeak's blocks are not full Block Closures.  In particular, 
there is only one activation context (lexical environment, in Scheme 
terminology) per block instance, rather than one per block invocation.  
One implication is that recursive invocations of blocks doesn't work.  
It also means that nested blocks can give surprising results.  For 
example:

|blocks|
blocks := (1 to: 10) collect: [:ea | [ea]].
blocks first value.  "you would expect this to be 1, but it is 10".

What's happening above is that every iteration through the collect 
block is sharing the same environment (actually it hijacks part of the 
enclosing method's environment), and so 'ea' is actually getting 
mutated each time through rather than new bindings being created.

This is basically a kludge that Squeak inherited from Smalltalk-80 and 
hasn't fixed yet.  VisualWorks Smalltalk, for example, does not have 
this limitation.

There's a package on SqueakMap called the ClosureCompiler that 
introduces a new compiler that produces proper Scheme-like Block 
Closures.  This is intended to be integrated into the mainstream Squeak 
release in the near future, although it's hard to say exactly when.  
Part of the problem is that currently it slows things down a fair bit 
because of all of the extra activation contexts.

If you're interested in "Smalltalk for Schemers", you should also look 
at the implementation of call-with-current-continuation used by the 
Seaside package.  It's always nice to blow the minds of Scheme folk by 
showing them that call/cc can be implemented in about 10 lines of code 
on top of an environment that wasn't built to have it.  See the class 
Continuation and its class side method #currentDo:.  I've done similar 
tricks to get a kind of tail-call elimination...

Avi




More information about the Squeak-dev mailing list