Carets in blocks WAS: Curying blocks

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

Carets in blocks WAS: Curying blocks

Fernando Rodríguez
>> curry := [:query| ^[:a :b| (a perform: query) < (b perform:
>>query)]]

>> I get a weird error: "Cannot return a Block closure to expired
>>context
>> or across processes".
>I think your problem here is the carret "^". This tells ST to >return
>from the method (context) in which the block was used. If you >assign
the
>block to a var and send it #value: later on the block get's >executed
in
>a BlockContext. And a block context cannot return from a >method ....

Yes, I gues you're right, my main problem is that I'm not sure when I
should include a caret inside a block. Can you give any pointers to
this isssue? O:-)

Thanks


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Hans-Martin Mosner
"Fernando" <[hidden email]> wrote:
...
> Yes, I gues you're right, my main problem is that I'm not sure when I
> should include a caret inside a block. Can you give any pointers to
> this isssue? O:-)

Very simple: the caret returns from the method invocation in which the
block was created, if that method invocation has not been returned from yet.

Cheers,
Hans-Martin


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Fernando Rodríguez
>Very simple: the caret returns from the method >invocation in which
the
>block was created, if that method invocation has not >been returned
from yet.

Thank you, I though it exited the block. However, this sounds a bit
drastic. What if I only want to prematurely exit the block, not the
method where it was defined?

Thanks.


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Udo Schneider
Fernando wrote:
> Thank you, I though it exited the block. However, this sounds a bit
> drastic. What if I only want to prematurely exit the block, not the
> method where it was defined?

Short answer - you can't. There is no such thing as a block return. A
block is allways executed completely and the result of the last
expression is returned.

You might work around this issue like this:

[ :return |
        return notNil ifTrue: [
                "some code"
                "just set return to a value to
                break out of the block and return"].
        return notNil ifTrue: [ "some code" ].
        return notNil ifTrue: [ "some code" ].
        return notNil ifTrue: [ "some code" ].
        return]

CU,

Udo


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Chris Uppal-3
In reply to this post by Fernando Rodríguez
Fernando wrote:

> What if I only want to prematurely exit the block, not the
> method where it was defined?

You can't.


And that's really then end of the story, but just for interest....

Actually there are a few "clever" methods for doing this, but I wouldn't
normally consider them for use in "real" code.  Here's one of them:

    BlockClosure>>repeatWithExit
        ^ [self value: [:result | ^ result]] repeat.

which can be used like:

    i := 0.
    [:exitWith |
    i > 10 ifTrue: [exitWith value: true].
    i := i + 1]
         repeatWithExit.

(And you can define #valueWithExit similarly)  I wouldn't mention this except
that your 'currying' example shows that you enjoy mind-benders ;-)

Another way, even scairier, is to do stack introspection. (this, Dolphin
specific, inplementation was suggested by Blair a few years ago -- so blame
him, not me ;-):

    BlockClosure class>>returnFromCurrentWith: anObject
        Processor activeProcess topFrame sender return: anObject.

which can be used like:

    [| i |
    i := 0.
    [i := i + 1.
    i > 10 ifTrue: [BlockClosure returnFromCurrentWith: true]]
        repeat.
    ] value.

HTH ;-)

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Reinout Heeck-3
In reply to this post by Fernando Rodríguez
Fernando wrote:

>>Very simple: the caret returns from the method >invocation in which
>
> the
>
>>block was created, if that method invocation has not >been returned
>
> from yet.
>
> Thank you, I though it exited the block. However, this sounds a bit
> drastic. What if I only want to prematurely exit the block, not the
> method where it was defined?


You will need to implement an additional control structure.

For a well-known idiom to implement a local return see
 
http://lists.squeakfoundation.org/pipermail/squeak-dev/2000-July/000132.html



Enjoy!

Reinout
-------


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Udo Schneider
Reinout Heeck wrote:
> You will need to implement an additional control structure.
>
> For a well-known idiom to implement a local return see
>
> http://lists.squeakfoundation.org/pipermail/squeak-dev/2000-July/000132.html 
I didn't know this one .... one more thing from the "bag of tricks"
category :-)

CU,

Udo


Reply | Threaded
Open this post in threaded view
|

Re: Carets in blocks WAS: Curying blocks

Hans-Martin Mosner
In reply to this post by Fernando Rodríguez
"Fernando" <[hidden email]> wrote:
> >Very simple: the caret returns from the method >invocation in which
> the
> >block was created, if that method invocation has not >been returned
> from yet.
>
> Thank you, I though it exited the block. However, this sounds a bit
> drastic. What if I only want to prematurely exit the block, not the
> method where it was defined?

Others already wrote that it is not possible, and there is a reason for
it, too: It would invite you to write needlessly complicated block
structures :-)
When you really need to have complicated control flow including early
return within a block, it's very likely that this block should become a
method instead.
There are some things in Smalltalk which at first glance seem to be
deficiencies, but once you think about them, they become hints by the
system that you're doing something slightly wrong (of course, there are
a few *real* deficiencies in Smalltalk, too...)

Cheers,
Hans-Martin