[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