Evolution of Smalltalk blocks

# Allen Wirfs-Brock (15 years ago)

(since this is really off topic, I've retitled this thread).

Here is my understand of the evolution of Smalltalk blocks. I wasn't around for the first two generations, but I was for the rest. Dan can correct any early history I got wrong.

  1. My understanding is that Smalltalk-72 did in fact operate pretty much as described in the Alan Kay quote. It was a pure textual interpreter and the text of argument expressions was passed to methods uninterpreted. It was up to the receiving method to interpret the argument text and (at least in theory) could impose any sort of syntax rules it wanted upon up. I don't know how scoping worked for such deferred code interpretation.

  2. When Dan implemented Smalltalk-76 as a bytecode compiler, textual interpretation went out the door. [ ] delimited code sequences became funargs. Block formal parameters were hoisted as local variables of their enclosing method. This created argument sharing and reentrancy issues for blocks. I believe this scheme was directly carried forward, perhaps with some minor tweaks, into the original Smalltalk-80 implementations. BTW, note that up to this point all activation records (MethodContexts and BlockContexts) were heap allocated objects.

  3. As various groups started trying to build high performance Smalltalk implementations on conventional hardware they started trying to stack allocate activations records. The hoisting of block arguments to the enclosing method context complicated this and was inefficient. Some implementations started allocating block arguments in the activation records of each block invocation. This resulted in faster blocks calls and less GC pressure. In some implementations it also fixed the block reentrancy problem. However, in some cases it changed or broke some user-level semantics such as nested blocks with arguments or sharing between method locals and block arguments.

  4. When implementers stepped back a bit from these problems, some of them realized that blocks were conceptually very similar to lexically nested first class functions and that closure capture semantics would fix all the problems. So, individual implementations and eventually the Smalltalk standard redefined them as such. Along the way, block local variables (in addition to formal parameters) were added as they pretty much just fell out of the design.

My impression (largely from the same sources that Brendan quoted) is that Alan Kay probably thinks that everything past step 1 above was a step backwards from the perspective of language expressibility.