BlockClosure vs BlockContext

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

BlockClosure vs BlockContext

John Chludzinski
I have some code that fixed the values of temps (in a BlockContext) at the point of definition (using #fixTemps).  Now I'm using Seaside 3.0 on Squeak 4.1 and the values of the block's temps is set at the point of call (when I evaluate the block) - block are now BlockClosure's.  How do I fix the temps to be the values where the block is defined?  

#fixTemps is now a no-op.

---John


Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

gcotelli
Hi John,
the newest images and VM has now proper closure support. There's no need for fixTemps anymore.

On Tue, Aug 3, 2010 at 7:50 PM, John Chludzinski <[hidden email]> wrote:
I have some code that fixed the values of temps (in a BlockContext) at the point of definition (using #fixTemps).  Now I'm using Seaside 3.0 on Squeak 4.1 and the values of the block's temps is set at the point of call (when I evaluate the block) - block are now BlockClosure's.  How do I fix the temps to be the values where the block is defined?  

#fixTemps is now a no-op.

---John






Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

John Chludzinski
In reply to this post by John Chludzinski
When I try:

test1

| block w z |
w := 3. z := 12.
block := [ Transcript show: w asString , '   ' , z asString; cr ].
w := 0. z := 1.
block value.

I get: 0  1.  And NOT: 3  12, which are the values at the point of definition.

How do I force the binding to (3 12)?

---John


On Tue, Aug 3, 2010 at 6:50 PM, John Chludzinski <[hidden email]> wrote:
I have some code that fixed the values of temps (in a BlockContext) at the point of definition (using #fixTemps).  Now I'm using Seaside 3.0 on Squeak 4.1 and the values of the block's temps is set at the point of call (when I evaluate the block) - block are now BlockClosure's.  How do I fix the temps to be the values where the block is defined?  

#fixTemps is now a no-op.

---John



Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

John Chludzinski
How about:

test1

| block w z |
w := 3. z := 12.
block := { [ :a :b | Transcript show: a asString , '   ' , b asString; cr ] . w . z }.
w := 0. z := 1.
(block at: 1) value: (block at: 2) value: (block at: 3) 


On Wed, Aug 4, 2010 at 12:39 AM, John Chludzinski <[hidden email]> wrote:
When I try:

test1

| block w z |
w := 3. z := 12.
block := [ Transcript show: w asString , '   ' , z asString; cr ].
w := 0. z := 1.
block value.

I get: 0  1.  And NOT: 3  12, which are the values at the point of definition.

How do I force the binding to (3 12)?

---John


On Tue, Aug 3, 2010 at 6:50 PM, John Chludzinski <[hidden email]> wrote:
I have some code that fixed the values of temps (in a BlockContext) at the point of definition (using #fixTemps).  Now I'm using Seaside 3.0 on Squeak 4.1 and the values of the block's temps is set at the point of call (when I evaluate the block) - block are now BlockClosure's.  How do I fix the temps to be the values where the block is defined?  

#fixTemps is now a no-op.

---John




Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Randal L. Schwartz
In reply to this post by John Chludzinski
>>>>> "John" == John Chludzinski <[hidden email]> writes:

John> When I try:
John> test1

John> | block w z |
John>  w := 3. z := 12.
John> block := [ Transcript show: w asString , '   ' , z asString; cr ].
John> w := 0. z := 1.
John>  block value.

John> I get: 0  1.  And NOT: 3  12, which are the values at the point of
John> definition.

John> How do I force the binding to (3 12)?

That's not how closures work.  I would have expected 0 1 as well.

If you want 3 12, you need to not update the one and only w and z later
in the method.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion

Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Randal L. Schwartz
In reply to this post by John Chludzinski
>>>>> "John" == John Chludzinski <[hidden email]> writes:

John> How about:
John> test1

John> | block w z |
John>  w := 3. z := 12.
John> block := { [ :a :b | Transcript show: a asString , '   ' , b asString; cr ]
John> . w . z }.
John> w := 0. z := 1.
John>  (block at: 1) value: (block at: 2) value: (block at: 3)

Yeah, now that closures work, you could effectively curry the values:

    | block w z |
    w := 3.
    z := 12.
    block :=
      [:captureW :captureZ |
        [Transcript show: captureW asString , ' ' , captureZ asString; cr]]
          value: w value: z.

    w := 0.
    z := 1.

    block value.  "should still show 3, 12"

There might even be a method for that... or it might have just been
Seaside specific.

In fact, that's sorta what fixTemps did before. :)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion

Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Randal L. Schwartz
>>>>> "Randal" == Randal L Schwartz <[hidden email]> writes:

>>>>> "John" == John Chludzinski <[hidden email]> writes:
John> How about:
John> test1

John> | block w z |
John> w := 3. z := 12.
John> block := { [ :a :b | Transcript show: a asString , '   ' , b asString; cr ]
John> . w . z }.
John> w := 0. z := 1.
John> (block at: 1) value: (block at: 2) value: (block at: 3)

Randal> Yeah, now that closures work, you could effectively curry the values:

Randal>     | block w z |
Randal>     w := 3.
Randal>     z := 12.
Randal>     block :=
Randal>       [:captureW :captureZ |
Randal>         [Transcript show: captureW asString , ' ' , captureZ asString; cr]]
Randal>           value: w value: z.

Randal>     w := 0.
Randal>     z := 1.

Randal>     block value.  "should still show 3, 12"

Randal> There might even be a method for that... or it might have just been
Randal> Seaside specific.

Ahh yes, #cull:cull:

    | block w z |
    w := 3.
    z := 12.
    block := [:newW :newZ | ... ] cull: w cull: z.
    w := 0.
    z := 1.
    block value.

Should do it.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion

Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Bert Freudenberg
In reply to this post by John Chludzinski

On 04.08.2010, at 00:50, John Chludzinski wrote:

> I have some code that fixed the values of temps (in a BlockContext) at the point of definition (using #fixTemps).  Now I'm using Seaside 3.0 on Squeak 4.1 and the values of the block's temps is set at the point of call (when I evaluate the block) - block are now BlockClosure's.  How do I fix the temps to be the values where the block is defined?  
>
> #fixTemps is now a no-op.
>
> ---John

Hmm. If we knew whether the closure actually used temps we could implement BlockClosure>>fixTemps as
       
        self hasTemps ifTrue: [
                self basicAt: self basicSize put: (self basicAt: self basicSize) copy]

But only the compiler seems to know, not the closure ...

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

John Chludzinski
In reply to this post by Randal L. Schwartz
So what are the semantics to BlockClosure's?  When are the values of temps bound to the block?


On Wed, Aug 4, 2010 at 11:02 AM, Randal L. Schwartz <[hidden email]> wrote:
>>>>> "Randal" == Randal L Schwartz <[hidden email]> writes:

>>>>> "John" == John Chludzinski <[hidden email]> writes:
John> How about:
John> test1

John> | block w z |
John> w := 3. z := 12.
John> block := { [ :a :b | Transcript show: a asString , '   ' , b asString; cr ]
John> . w . z }.
John> w := 0. z := 1.
John> (block at: 1) value: (block at: 2) value: (block at: 3)

Randal> Yeah, now that closures work, you could effectively curry the values:

Randal>     | block w z |
Randal>     w := 3.
Randal>     z := 12.
Randal>     block :=
Randal>       [:captureW :captureZ |
Randal>         [Transcript show: captureW asString , ' ' , captureZ asString; cr]]
Randal>           value: w value: z.

Randal>     w := 0.
Randal>     z := 1.

Randal>     block value.  "should still show 3, 12"

Randal> There might even be a method for that... or it might have just been
Randal> Seaside specific.

Ahh yes, #cull:cull:

   | block w z |
   w := 3.
   z := 12.
   block := [:newW :newZ | ... ] cull: w cull: z.
   w := 0.
   z := 1.
   block value.

Should do it.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion



Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Julian Fitzell-2
On Wed, Aug 4, 2010 at 5:44 PM, John Chludzinski
<[hidden email]> wrote:
> So what are the semantics to BlockClosure's?  When are the values of temps
> bound to the block?

The *values* aren't "bound". Closures "close over" the dynamic scope
at the point they are defined. This means that the variable references
in the closure refer to whatever variable bindings had those names at
the time the closure was created.

The point of #fixTemps was never to change this behaviour but rather
to make sure that variables defined *local to the closure* (such as
the parameter "a" in the examples below) behaved like unique variables
rather than being shared by all blocks in the same method.

i.e. In a closure image:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
blocks collect: [ :ea | ea value ] "--> #(1 2 3)"

Note that the :a is akin to a method parameter. Every time you call a
method, a new binding is created with that name and assigned the value
passed in. Multiple invocations of the method are not using the same
variable (otherwise recursion wouldn't work). Closures should behave
the same way.

In a non-closure image, however:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
blocks collect: [ :ea | ea value ] "--> #(3 3 3)"

or even more perversely:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
[ :a | ] value: 4.
blocks collect: [ :ea | ea value ] "--> #(4 4 4)"

but with fixTemps it behaves as in the closure image:

blocks := #(1 2 3) collect: [ :a | [ a ]  fixTemps ].
blocks collect: [ :ea | ea value ] "--> #(1 2 3)"


Note that even in a closure image, you *can* change the value of a
block-local variable after the fact (I've added a local variable
because you aren't allowed to change the value of "a", since it's a
parameter):

getters := OrderedCollection new.
setters := OrderedCollection new.
#(1 2 3) do: [ :a |
        |local|
        local := a.
        getters add: [ local ].
        setters add: [ :val | local := val ] ].
getters collect: [ :ea | ea value ]. "--> #(1 2 3)"
setters do: [ :ea | ea value: 9 ].
getters collect: [ :ea | ea value ]. "--> #(9 9 9)"

Hope that helps some (and provides food for thought :) )?

Julian

Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Julian Fitzell-2
In reply to this post by John Chludzinski
(sorry, reposting as I didn't reply to all and missed some lists)

On Wed, Aug 4, 2010 at 5:44 PM, John Chludzinski
<[hidden email]> wrote:
> So what are the semantics to BlockClosure's?  When are the values of temps
> bound to the block?

The *values* aren't "bound". Closures "close over" the dynamic scope
at the point they are defined. This means that the variable references
in the closure refer to whatever variable bindings had those names at
the time the closure was created.

The point of #fixTemps was never to change this behaviour but rather
to make sure that variables defined *local to the closure* (such as
the parameter "a" in the examples below) behaved like unique variables
rather than being shared by all blocks in the same method.

i.e. In a closure image:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
blocks collect: [ :ea | ea value ] "--> #(1 2 3)"

Note that the :a is akin to a method parameter. Every time you call a
method, a new binding is created with that name and assigned the value
passed in. Multiple invocations of the method are not using the same
variable (otherwise recursion wouldn't work). Closures should behave
the same way.

In a non-closure image, however:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
blocks collect: [ :ea | ea value ] "--> #(3 3 3)"

or even more perversely:

blocks := #(1 2 3) collect: [ :a | [ a ] ].
[ :a | ] value: 4.
blocks collect: [ :ea | ea value ] "--> #(4 4 4)"

but with fixTemps it behaves as in the closure image:

blocks := #(1 2 3) collect: [ :a | [ a ]  fixTemps ].
blocks collect: [ :ea | ea value ] "--> #(1 2 3)"


Note that even in a closure image, you *can* change the value of a
block-local variable after the fact (I've added a local variable
because you aren't allowed to change the value of "a", since it's a
parameter):

getters := OrderedCollection new.
setters := OrderedCollection new.
#(1 2 3) do: [ :a |
       |local|
       local := a.
       getters add: [ local ].
       setters add: [ :val | local := val ] ].
getters collect: [ :ea | ea value ]. "--> #(1 2 3)"
setters do: [ :ea | ea value: 9 ].
getters collect: [ :ea | ea value ]. "--> #(9 9 9)"

Hope that helps some (and provides food for thought :) )?

Reply | Threaded
Open this post in threaded view
|

Re: BlockClosure vs BlockContext

Randal L. Schwartz
>>>>> "Julian" == Julian Fitzell <[hidden email]> writes:

Julian> #(1 2 3) do: [ :a |
Julian>        |local|
Julian>        local := a.
Julian>        getters add: [ local ].
Julian>        setters add: [ :val | local := val ] ].
Julian> getters collect: [ :ea | ea value ]. "--> #(1 2 3)"
Julian> setters do: [ :ea | ea value: 9 ].
Julian> getters collect: [ :ea | ea value ]. "--> #(9 9 9)"

((1 to: 3) collect:
  [:a |
    | local |
    local := a.
    [local] -> [:b | local := b]]) asDictionary

:-)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc.
See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion