Is there any way to explicitly return from a BlockContext/BlockClosure (like ^some-expression in methods) but without returning from the parent context (method)? I'm beginning to figure out how to avoid the need for "break&continue" in loops, and i know that i can even avoid the need for explicit return converting the block in question in a method, but there are places where a long block is much more convenient... thanks vsv
Viktor Svub a écrit :
Is there any way to explicitly return from a BlockContext/BlockClosure (like ^some-expression in methods) but without returning from the parent context (method)? I'm beginning to figure out how to avoid the need for "break&continue" in loops, and i know that i can even avoid the need for explicit return converting the block in question in a method, but there are places where a long block is much more convenient... thanks
Hi, I don't know if it is possible, but most of the time, when I need it, it is a sign that I do not use the good abstraction. For example, I need to replace #do: by #detect: or things like this.
example
| cont j |
cont _ Continuation current. cont isNumber ifTrue: [^ cont]. 1 to: 5 do: [:i | j _ i. i = 3 ifTrue: [cont value: i]].
^ j.
this return 3 via ^cont so you can actually do whatever you want with that value, just as you asked.
... you can find class Continuation in Seaside.
Stef
Viktor Svub wrote:
Is there any way to explicitly return from a BlockContext/BlockClosure (like ^some-expression in methods) but without returning from the parent context (method)? I'm beginning to figure out how to avoid the need for "break&continue" in loops, and i know that i can even avoid the need for explicit return converting the block in question in a method, but there are places where a long block is much more convenient... thanks vsv
Hi Viktor,
on Tue, 27 Jun 2006 09:23:15 +0200, you wrote:
Is there any way to explicitly return from a BlockContext/BlockClosure (like ^some-expression in methods) but without returning from the parent context (method)?
You can move the block into another method and do the [^ return] there. This will keep your calling method (your parent) active.
I'm beginning to figure out how to avoid the need for "break&continue" in loops,
Ah, the GOF break&continue world ;-)
and i know that i can even avoid the need for explicit return converting the block in question in a method, but there are places where a long block is much more convenient...
Yes, I also prefer to have all blocks in the same method. But under rare circumstances some block has to be moved "out of the way" and this perhaps befits your example.
I have methods that just create a block, like
makeBlock ^ [^ do this and that]
useBlock collection do: self makeBlock
HTH.
/Klaus
thanks vsv
Implement
BlockClosure>>valueWithExit ^self value: [^nil]
And then you can break
[ :break | 1 to: 10 do: [ :each | each = 7 ifTrue: [ break value ] ] ] valueWithExit
and continue
1 to: 10 do: [ :each | [ :continue | each = 7 ifTrue: [ continue value ] ] valueWithExit ]
but actually, I never had any reason to use this except when porting algorithms from Fortran or C...
----- Original Message ----- From: "Viktor Svub" gilrandir@centrum.cz To: squeak-dev@lists.squeakfoundation.org Sent: Tuesday, June 27, 2006 9:23 AM Subject: explicit return from a block
Is there any way to explicitly return from a BlockContext/BlockClosure (like ^some-expression in methods) but without returning from the parent context (method)? I'm beginning to figure out how to avoid the need for "break&continue" in loops, and i know that i can even avoid the need for explicit return converting the block in question in a method, but there are places where a long block is much more convenient... thanks vsv
Implement
BlockClosure>>valueWithExit ^self value: [^nil]
In the visitors of Pier I use a similar pattern to jump to certain states in the visitor. In Scheme this pattern is commonly done using continuations, but since I always jump upwards the stack it is more efficient to use blocks in Squeak.
Object>>withEscaper: aBlock ^ aBlock value: [ :value | ^ value ]
Then you can then do something like:
self withEscaper: [ :break | aCollection do: [ :each | self withEscaper: [ :continue | .... ... ifTrue: [ break value: result1 ]. ... ifFalse: [ continue value: result2 ]. .... ] ]
Cheers, Lukas
squeak-dev@lists.squeakfoundation.org