[squeak-dev] Really strange problem

Levente Uzonyi leves at elte.hu
Tue Jan 18 13:21:27 UTC 2011


On Tue, 18 Jan 2011, Casimiro de Almeida Barreto wrote:

> Hello,
>
> I'm writing an example (a message for calculating combinations out of a
> collection and I found an amazing error. When line combOfRest :=
> workList combinations: (n - 1) is called VM tries to evaluate things in
> the self context (as if workList was self) and then x is nil and that
> causes an error. Is this behavior expected?

Which VM and image do you use? (I couldn't reproduce this problem.)

But I found a bug in your code. This line:
                 (combOfRest at: j) add: x before: 1 ].
should probably be:
                 (combOfRest at: j) addFirst: x ].

And there's another bug(?) which causes your method to sometimes return a 
hierarchical structure instead of simply a collection of collections. But 
you shouldn't bother with it, because this method can be implemented much 
easier:

SequenceableCollection >> combinations: n

 	^Array streamContents: [ :stream |
 		self combinations: n atATimeDo: [ :each |
 			stream nextPut: each copy ] ]


Levente

>
> I was expecting that workList combinations: x would be executed in a new
> context (since it's an instance of IntegerArray)
>
> By the way, when I inspect I discover that there are 3 instances of x
> (one with right value, and two nil).
>
> CdAB
>
>    IntegerArray>>combinations: n
>        "This message returns all possible combinations of n elements
>    from self"
>
>        | theCombinations workList |
>
>        "First let's check conditions"
>        n class ~= SmallInteger ifTrue: [ self error: 'argument should
>    be SmallInteger but is: ',n class asString ].
>        (n < 1 or: [ n > self size ]) ifTrue: [ self error: 'argument
>    out of range: ',n asString ].
>
>        theCombinations := OrderedCollection new.
>
>        "Basic case #1: size equals to data size"
>        n = self size ifTrue: [
>            | x |
>            x := OrderedCollection newFrom: self.
>            theCombinations add: x.
>            ^theCombinations ].
>
>        "Basic case #2: size equals to 1"
>        n = 1 ifTrue: [
>            1 to: self size do: [ :i |
>                | x |
>                x := OrderedCollection with: (self at: i).
>                theCombinations add: x ].
>            ^theCombinations ].
>
>        workList := self class newFrom: self.
>
>        "Generic case"
>        1 to: self size - n + 1 do: [ :i |
>            | x combOfRest |
>
>            x := workList at: 1.
>
>            workList := workList allButFirst.
>
>            *combOfRest := workList combinations: (n - 1)*.
>
>            1 to: combOfRest size do: [ :j |
>                (combOfRest at: j) add: x before: 1 ].
>
>            theCombinations add: combOfRest ].
>
>        ^theCombinations
>
>
>
>
>
>
>



More information about the Squeak-dev mailing list