Two ensure: questions

Andreas Raab Andreas.Raab at gmx.de
Mon Apr 22 21:05:14 UTC 2002


Andres,

> Let's say you evaluate this in a workspace.
> 
> 	[^self] ensure: [x := 1]
> 
> The ANSI spec says that ensure: should evaluate the receiver and,
> immediately after evaluation but before returning its result, the
> terminator block should be evaluated.  But the block is ^self: how do
> you evaluate without returning?  Actually, the block doesn't even
> "return" a value, it just caret-returns from it's method context.  The
> text from the ANSI spec is not conclusive in this matter.

It's actually pretty clear if you consider that the return is first from
the block and then from the method. E.g., let's simplify the above first
to

	[^self] value.

then, another way of writing the above would be:

	[blockResult := self] value.
	^blockResult

Now, if we add #ensure the second version results in

	[blockResult := self] ensure:[x := 1].
	^blockResult

and clearly x should be one in this case.

> Should x be 1 or nil?  And if x should be 1, how do you implement
> ensure: in Smalltalk so that you can figure out a block is
> caret-returning on you?

Heh, heh. By catching non-local returns through unwind contexts. The
Squeak VM has specific support for it (done by Tim and some others)
which marks unwind contexts (if you look at #ensure: you will see that
it has an associated primitive number) and sees if a non-local return
goes across any of those specially marked contexts. If so, it sends a
special message (#aboutToReturn:through:) which does the rest. I think
this is how it works in pretty much all other Smalltalks (although the
details may differ wildly).

Cheers,
  - Andreas




More information about the Squeak-dev mailing list