On Sun, 26 Aug 2012, Frank Shearar wrote:
On 26 August 2012 17:55, Levente Uzonyi <[email protected]> wrote:
On Sun, 26 Aug 2012, Frank Shearar wrote:
That sounds like a reasonable workaround to address Mariano's
immediate problem :)
I don't see what other issues are there to solve. :)
Then you should go reread my article, and the articles it references
:) Both have examples of how undelimited dynamic variables don't work
sensibly with delimited continuations. Kiselyov goes further and shows
how they _cannot_ work sensibly.
I took a look why DynamicVariable doesn't work with Control and I
found that the reason is that Control doesn't play well with #ensure:.
Let's see it in this example:
DynamicVariable value: 1 during: [
[ DynamicVariable value: 2 during: [
[ :k | DynamicVariable value ] shift ]] reset ]
When #reset is sent, the value of the variable is 1, then it starts
evaluating the receiver block. The value is set to 2 and then #shift
occurs. #shift cuts the stack back, so the argument of #ensure:, which
would restore the value of the variable in the process' environment to 1
is never evaluated.
So Control breaks the contract of #ensure:, because it starts the
evaluation of its receiver, but doesn't evaluate its argument:
x := 0.
[
[
x := 1.
[ :k | x ] shift ]
ensure: [ x := 2 ] ] reset.
"==> 1"
Serialising a running process implicitly creates a delimited
continuation. Ergo, Fun Times!
frank
Anyway, here's a highly
untested example of what I had in my mind:
http://leves.web.elte.hu/squeak/StackSerializableDynamicVariable.st
Yep, using resumable exceptions to implement delimited dynamic
variables. That's exactly what Control does, only without
DynamicVariable necessarily polluting the global namespace.
The most common use case of DynamicVariable involves accessing the
variable from "unrelated" places. Using the global namespace is an easy
way to avoid passing the variable around all the time. It's basically the
same as subclassing Notification (which is a common practice - a pattern -
to implement dynamic variables) from this POV.
Is uses a method in Process which is not present in current images:
environmentAt: key ifAbsentPut: aBlock
^(env ifNil: [ env := Dictionary new ]) at: key ifAbsentPut: aBlock.
Current _Pharo_ images, maybe. I'm pretty sure I looked at a trunk
image with it in the last few hours (but obviously am too lazy to
actually go check :/)
I just wrote this method, so I'm pretty sure it's not present in any
image. :)
Levente
frank
Levente