[squeak-dev] A little puzzle
Mateusz Grotek
unoduetre at poczta.onet.pl
Thu May 14 22:42:51 UTC 2015
Dnia 14.05.2015 17:33:45, Stéphane Rollandin napisał(a):
> Hello all,
>
> I'm finding myself unable to implement something seemingly simple.
> Here is the puzzle:
>
> I want an iterator factory which, given a specific collection,
> produces a block taking two arguments, also blocks. One (the doBlock)
> tells what should be done for each element of the collection, and the
> other (the whileBlock) is a test allowing to abort the whole
> operation.
>
> So, something like this:
>
> Puzzle>>blockIterating: aCollection
>
> ^ [:doBlock :whileBlock |
> aCollection do: [:i |
> (whileBlock value: i) ifFalse: [^ self].
> doBlock value: i]].
>
>
> Then I could do things like the following:
>
>
> | block |
>
> block := Puzzle new blockIterating: (1 to: 5).
>
> block value: [:p | Transcript show: p; cr] value: [:p | p < 3]
>
>
>
> But the above fails with a 'Block cannot return' (that's the [^ self]
> block in the #blockIterating: method). I have attached the code; just
> do "Puzzle new fail".
>
> I can't find a workaround.
>
> How should I proceed to get a working iterator block ?
>
> Stef
The behaviour is correct. The ^ operator has lexical scope. It returns
from the lexically enclosing method.
In this case it would return from blockIterating:, but at this point
the method has already returned, so you cannot return from it the
second time.
What you really want is another method. Just use two separate methods:
for: aCollection do: aDoBlock unless: aWhileBlock
aCollection do: [:i |
(whileBlock value: i) ifFalse: [^ self].
doBlock value: i
]
blockIterating: aCollection
[:doBlock :whileBlock |
self for: aCollection do: doBlock while: whileBlock
].
More information about the Squeak-dev
mailing list
|