Lexical closures in Squeak

Stephen Pair spair at acm.org
Mon Aug 12 16:12:51 UTC 2002


Jason,

A BlockContext accesses variables (temporary variables and instance
variables) through its home context (a MethodContext).  When you call
StateMachine>>forkNextTrackProcess a new MethodContext is created on
that CompiledMethod.  The variable "delay" is a temporary variable
stored in the MethodContext, while the variable "terminating" is an
instance variable of the receiver.

The issue with BlockContexts in Squeak arises when one stores a
BlockContext somewhere and then later tries to evaluate it.  When a
block is evaluated, there is no new evaluation structure created, and
thus it's dangerous to concurrently evaluate the same block (and in fact
Squeak disallows this).  Two concurrently running blocks would be
attempting to access the very same slots for any temporary variables (in
the associated home MethodContext).  Additionally, if the block takes
arguments, after evaluation the block will retain pointers to those
arguments because those arguments are also stored in the block's home
MethodContext.  This can needlessly prevent objects from being garbage
collected.

You might open an inspector on a BlockContext (that takes one argument)
and it's related home MethodContext.  Send the #value: message to the
block and observe that it's being stored in the related home
MethodContext.  You can also refer to a temporary variable in the Block
and see that it is also stored in the home MethodContext.

Evaluate the following in a workspace:

| temp |
temp := 1.
delay := Delay forSeconds: 1.
([ :x | temp := temp + 1. delay wait. x hash ]
	inspect;
	home) inspect

You will see an inspector on the BlockContext, and another on it's home
MethodContext.  The MethodContext will have 2 indexed slots where it
stores the values for temp and x respectively.  If you evaluate "self
value: 'a'" in the BlockContext's inspector (and wait 1 second) you'll
notice that these values (in MethodContext) get updated.  You'll also
noticed that even after the evaluation of the block is complete, that
the MethodContext is still holding onto 'a'.  If you evaluate:

[self value: 'a'] fork.
[self value: 'b'] fork.

In the BlockContext's inspector, you'll get the error: 'Attempt to
evaluate a block that is already being evaluated.'

- Stephen

> -----Original Message-----
> From: squeak-dev-admin at lists.squeakfoundation.org 
> [mailto:squeak-dev-admin at lists.squeakfoundation.org] On 
> Behalf Of Jason Dufair
> Sent: Monday, August 12, 2002 11:32 AM
> To: squeak-dev at lists.squeakfoundation.org
> Subject: Lexical closures in Squeak
> 
> 
> With my recent venture into spawning Squeak processes, I have a 
> question.  From having lurked on the list for many months, I am under 
> the impression that Squeak's blocks are not true lexical 
> closures (and 
> that someone(s) are working toward this).  If this is true, then why 
> does something like (forgive any errors - I'm going from memory)
> 
> StateMachine>>forkNextTrackProcess
> 
>    [ | delay |
>     delay _ Delay forMilliseconds: 300.
>     [terminating]
>         whileFalse:
>             [streamingMp3File samplesRemaining = 0
>                 ifTrue: [self nextTrack].
>                 Process waitFor: delay]] fork.
> 
> work?  'terminating' is an instance variable of StateMachine, by the 
> way.  It would seem that this wouldn't be possible without 
> true lexical 
> closure.  I'm no CS major, so please speak slowly and avoid 
> polysyllabic 
> words :-)
> 
> -- 
> Jason Dufair - jase at dufair.org
> http://www.dufair.org/
> "In matters of style, swim with the current; 
> in matters of principle, stand like a rock."
> -- Thomas Jefferson
> 
> 
> 
> 




More information about the Squeak-dev mailing list