[Newbies] Block and Closure

Ralph Johnson johnson at cs.uiuc.edu
Fri Apr 10 16:09:33 UTC 2009


In the original Smalltalk, blocks were almost but not quite closures.
The ANSII standard says they are closures.  As far as I know, all the
Smalltalks except Squeak make blocks be closures.  So, changing the
way Squeak implements blocks will bring it into compliance with the
standard and more like other implementations of Smalltalk

I first ran into the problem of blocks not being closures when I tried
to write a program like

(1 to: 100) do: [:each | [self process: each] fork]

This will fork 100 processes.  If the first spawned process (the one
running [self process: 1]) starts to run right away, it will behave
like I expect.  But suppose the main thread creates all 100 processes
before it gives up control.  Then the value of "each" will be 100 and
so all 100 processes will execute [self process: 100], which is not at
all what I expect.  If blocks were closures then each execution of the
block would have its own context to store its argument, i.e. there
would be 100 versions of "each".

You can see a similar problem if you try to implement factorial the
way that Scheme programmers do it.

|factBlock|
factBlock := [:x | x <= 1 ifTrue: [1] ifFalse: [x * (factBlock value: x-1)]].
factBlock value: 100

Squeak complains that you are trying to evaluate a block recursively.
Most Smalltalk programmers would never try this, so they don't care
about Squeak's limitations.  But people coming to Squeak from a
functional programming language are annoyed, because they expect that
they can do this with blocks, but blocks are not complete closures.

-Ralph Johnson


More information about the Beginners mailing list