Are Squeak blocks like Scheme blocks
Last updated at 3:53 pm UTC on 14 January 2006
Question Aaron Lanterman February 24, 2004: 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)?
I believe the answer is yes based on my reading and playing around in Squeak, but I wanted to check to see if there was a subtlety I was missing.
I was mentally brainstorming today something like a "Smalltalk for Schemers" tutorial - trying to reconcile the "oo programming rules" with the "functional programming rules" mindsets. I then got the twisted idea to try writing the Y-combinator using blocks.
Answer Avi Bryant: 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 := (1 to: 10) collect: [:each | [each]].
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 'each' 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...
Answer Anthony Hannan [Regarding observation that in the latest 3.7, ClosureCompiler “the image slowed down tremendously. I understand the VM needs rebuilt.”]
The block closure prims were built into the 3.6.2 Windows VM (which is the latest one, dated 11/12/03), so use that one.