[Self-interest] Block Question

Jecel Assumpcao Jr jecel at merlintec.com
Mon Nov 8 20:21:24 UTC 2021


Luke McNeil wrote on Sat, 6 Nov 2021 18:15:37 -0400
> I'm trying to figure out why the code "(| x = [1] |) x value" throws this error "cannot run a block after its enclosing method has returned."
> What object exactly is the block's enclosing method, and when is it created?
> My best guess would be that when "[1]" is evaluated to be placed in slot x, it is actually evaluated in the context of a new empty method activation object.
> I realize that this code isn't really useful (it throws an error after all), but I am just trying to better understand what Self is doing.

If in Self or Smalltalk you are executing message A and send message B
and then that sends message C, eventually C will return and even later B
will return and you will be back in A. This is the traditional "stack
discipline" and is very efficient to implement.

Blocks complicate this simple picture. If a block is created inside B it
will need to use stuff B keeps in its stack frame when it runs. That
will happen when someone sends the "value" message to that block. But
what if B has already returned to A at that point in time?

One solution, adopted by nearly all Smalltalks, is to declare that B's
stack frame will have to stick around. We can hold it in a regular
object and let the garbage collector take care of eventualy getting rid
of it. Quite a bit o the complexity of high performance Smalltalk
virtual machine implementations is in dealing with this problem.

An alternative, adopted by Self, is to simply declare this to be an
error - the one you saw. You are allowed to use blocks created in B as
long as its stack frame is still around. When B returns we just throw
all its stuff away (pop the stack) and too bad if any blocks needed it.
Not having these "non LIFO blocks" in Self doesn't hurt like it would in
other Smalltalks because it is so simple to create new kinds of objects.
So if we want some data and code fragment to be usable after the method
that created has finished we simply use an object instead of a block. It
is just a matter of parenthesis instead of square brackets (not counting
that blocks have lexical scoping and objects don't).

Note that even people who made this design decision sometimes regret it.
It was certainly a key obstacle in Mario's getting GNU Smalltalk code to
run in Self.

-- Jecel


More information about the Self-interest mailing list