[squeak-dev] A little puzzle
Stéphane Rollandin
lecteur at zogotounga.net
Thu May 14 18:47:27 UTC 2015
Ah, so that's the bottom line. Thanks a lot ! I'm now trying to wrap my
head around these concepts...
It looks like I could also get the return block as an outside argument,
like this:
Puzzle>>blockIterating: aCollection
^ [:returnBlock |
[:doBlock :whileBlock |
aCollection do: [:i |
(whileBlock value: i) ifFalse: returnBlock.
doBlock value: i]]].
and then use it as follow:
| block |
block := (Puzzle new blockIterating: (1 to: 5)) value: [ ^self].
block value: [:p | Transcript show: p; cr] value: [:p | p < 3]
A bit hard to read but it seems to work. Does that make sense ?
Stef
> Returning from a block means returning from the method containing that
> block. (There's no syntax for block return in Smalltalk, because you'd
> have to be able to tell which block you want to return from to make that
> be of any use, but blocks are anonymous methods. If you need a named
> method, then use one.).
> You get that error, because you've already returned from the method (the
> block itself was returned), and it's not possible to return twice from the
> same context.
> One easy way to make it work is to send a message from inside the block,
> because then you'll have a separate context to return from.
> E.g.:
>
> Puzzle >> #blockIterating: aCollection
>
> ^[ :doBlock :whileBlock |
> self iterate: aCollection do: doBlock while: whileBlock ].
>
> Puzzle >> #iterate: aCollection do: doBlock while: whileBlock
>
> aCollection do: [ :each |
> (whileBlock value: each) ifFalse: [ ^self ].
> doBlock value: each ]
>
> Levente
>
> On Thu, 14 May 2015, Stéphane Rollandin wrote:
>
>> 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
>>
>
>
>
>
More information about the Squeak-dev
mailing list
|