valueWithReceiver for BlockClosures?

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

valueWithReceiver for BlockClosures?

Yoshiki Ohshima-3
I have a potential application of valueWithReceiver for BlockClosures
(not CompiledMethod) in my little project.  It'd start with something
like:

k1 := Dictionary new.
k1 at: #foo put: 3.
k1 at: #bar put: 4.

k2 := Dictionary new.
k2 at: #foo put: 6.
k2 at: #bar put: 8.

and then a closure is created in the context of k1 (thus "self" in the
following is k1):

self at: #block put: [(self at: #foo) + (self at: #bar)]

Then later, I'd like to "steal" the block from k1 and evaluate it in
the context of k2:

(k1 at: #block) valueWithReceiver: k2.

to get 14 instead of 7.  (Otherwise, in my application, the "equal"
closure that only differ in their "self" would be created many, many
times.  So, I want to share them.)

....

And Bert told me that I can just store "k2" into the outerContext's
receiver and it works.  As long as there is no concurrent invocation,
it'd just work.  Do people see other potential problems?

--
-- Yoshiki

Reply | Threaded
Open this post in threaded view
|

Re: valueWithReceiver for BlockClosures?

Eliot Miranda-2



On Mon, Jan 21, 2013 at 10:29 AM, Yoshiki Ohshima <[hidden email]> wrote:
I have a potential application of valueWithReceiver for BlockClosures
(not CompiledMethod) in my little project.  It'd start with something
like:

k1 := Dictionary new.
k1 at: #foo put: 3.
k1 at: #bar put: 4.

k2 := Dictionary new.
k2 at: #foo put: 6.
k2 at: #bar put: 8.

and then a closure is created in the context of k1 (thus "self" in the
following is k1):

self at: #block put: [(self at: #foo) + (self at: #bar)]

Then later, I'd like to "steal" the block from k1 and evaluate it in
the context of k2:

(k1 at: #block) valueWithReceiver: k2.

to get 14 instead of 7.  (Otherwise, in my application, the "equal"
closure that only differ in their "self" would be created many, many
times.  So, I want to share them.)

....

And Bert told me that I can just store "k2" into the outerContext's
receiver and it works.

Phhh... yes, sort-of.  But the outerContext could be shared by other blocks.  So safest is to copy the outerContext and change the receiver in the copy.  But since you're doing this to save space and you really, really know what you're doing, do it Bert's way.

But IMO it's far from safe for a base image facility, because

a) one should really change the receiver along the static chain as the block may be nested within other blocks.

b) one can't tell, without resort to slow allOwners-style code, if the outerContext is shared by other blocks.

So this is a really hairy hack that isn't safe in general, but is really neat in the right context.

 
 As long as there is no concurrent invocation,
it'd just work.  Do people see other potential problems?

Apart form the above no.  But why not simply rewrite as

    self at: #block put: [:scope| (scope at: #foo) + (scope at: #bar)]

and later do

    (k1 at: #block) value: k1

?


--
-- Yoshiki




--
best,
Eliot


Reply | Threaded
Open this post in threaded view
|

Re: valueWithReceiver for BlockClosures?

Yoshiki Ohshima-3
On Mon, Jan 21, 2013 at 4:27 PM, Eliot Miranda <[hidden email]> wrote:

>
>
>
> On Mon, Jan 21, 2013 at 10:29 AM, Yoshiki Ohshima <[hidden email]>
> wrote:
>>
>> I have a potential application of valueWithReceiver for BlockClosures
>> (not CompiledMethod) in my little project.  It'd start with something
>> like:
>>
>> k1 := Dictionary new.
>> k1 at: #foo put: 3.
>> k1 at: #bar put: 4.
>>
>> k2 := Dictionary new.
>> k2 at: #foo put: 6.
>> k2 at: #bar put: 8.
>>
>> and then a closure is created in the context of k1 (thus "self" in the
>> following is k1):
>>
>> self at: #block put: [(self at: #foo) + (self at: #bar)]
>>
>> Then later, I'd like to "steal" the block from k1 and evaluate it in
>> the context of k2:
>>
>> (k1 at: #block) valueWithReceiver: k2.
>>
>> to get 14 instead of 7.  (Otherwise, in my application, the "equal"
>> closure that only differ in their "self" would be created many, many
>> times.  So, I want to share them.)
>>
>> ....
>>
>> And Bert told me that I can just store "k2" into the outerContext's
>> receiver and it works.
>
>
> Phhh... yes, sort-of.  But the outerContext could be shared by other blocks.
> So safest is to copy the outerContext and change the receiver in the copy.
> But since you're doing this to save space and you really, really know what
> you're doing, do it Bert's way.
>
> But IMO it's far from safe for a base image facility, because
>
> a) one should really change the receiver along the static chain as the block
> may be nested within other blocks.
>
> b) one can't tell, without resort to slow allOwners-style code, if the
> outerContext is shared by other blocks.
>
> So this is a really hairy hack that isn't safe in general, but is really
> neat in the right context.
>
>
>>
>>  As long as there is no concurrent invocation,
>> it'd just work.  Do people see other potential problems?
>
>
> Apart form the above no.  But why not simply rewrite as
>
>     self at: #block put: [:scope| (scope at: #foo) + (scope at: #bar)]
>
> and later do
>
>     (k1 at: #block) value: k1
>
> ?

I thought of it and I thought I could not do it (this is a language
that is compiled to Squeak, and I could not think a good compilation
scheme).  But now, with your insistence, I think it is really easy,
actually^^;

Thanks!

--
-- Yoshiki