Enhancing SequenceableCollection>>combinationsAt:in:after:do:

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

Enhancing SequenceableCollection>>combinationsAt:in:after:do:

Runar Jordahl
In Pharo 1.3, SequenceableCollection>>combinations:atATimeDo: will,
for all combinations, send the same collection instance as argument
for the block. Therefore, if you use this collection itself, you will
be surprised:

|answer|
answer := OrderedCollection new.
#(a b c) combinations: 2 atATimeDo: [:each | answer add: each].
answer

Here I expect to end up with a collection looking like this:
1:  #(#a #b)
2:  #(#a #c)
3:  #(#b #c)

But I end up with:
1:  #(#c #c)
2:  #(#c #c)
3:  #(#c #c)

One fix is to change the client code to copy the argument for the block:
|answer|
answer := OrderedCollection new.
#(a b c) combinations: 2 atATimeDo: [:each | answer add: each copy].
answer

Another solution is enhancing
SequenceableCollection>>combinationsAt:in:after:do: to copy the
collection:
nn + 1 to: self size do: [ :index |
                aCollection at: jj put: (self at: index).
                jj = aCollection size
                        ifTrue: [ aBlock value: aCollection copy ]
                        ifFalse: [
                                self
                                        combinationsAt: jj + 1
                                        in: aCollection
                                        after: index
                                        do: aBlock ] ]



Kind regards
Runar Jordahl
blog.epigent.com

Reply | Threaded
Open this post in threaded view
|

Re: Enhancing SequenceableCollection>>combinationsAt:in:after:do:

Stéphane Ducasse
Thanks

can you propose some tests?
Did you sign the license agreement?

Stef

On Nov 2, 2011, at 7:57 PM, Runar Jordahl wrote:

> In Pharo 1.3, SequenceableCollection>>combinations:atATimeDo: will,
> for all combinations, send the same collection instance as argument
> for the block. Therefore, if you use this collection itself, you will
> be surprised:
>
> |answer|
> answer := OrderedCollection new.
> #(a b c) combinations: 2 atATimeDo: [:each | answer add: each].
> answer
>
> Here I expect to end up with a collection looking like this:
> 1:  #(#a #b)
> 2:  #(#a #c)
> 3:  #(#b #c)
>
> But I end up with:
> 1:  #(#c #c)
> 2:  #(#c #c)
> 3:  #(#c #c)
>
> One fix is to change the client code to copy the argument for the block:
> |answer|
> answer := OrderedCollection new.
> #(a b c) combinations: 2 atATimeDo: [:each | answer add: each copy].
> answer
>
> Another solution is enhancing
> SequenceableCollection>>combinationsAt:in:after:do: to copy the
> collection:
> nn + 1 to: self size do: [ :index |
> aCollection at: jj put: (self at: index).
> jj = aCollection size
> ifTrue: [ aBlock value: aCollection copy ]
> ifFalse: [
> self
> combinationsAt: jj + 1
> in: aCollection
> after: index
> do: aBlock ] ]
>
>
>
> Kind regards
> Runar Jordahl
> blog.epigent.com
>