Never use #newFrom: with associations from another dictonary if you reuse the first after.
The bug is actually deeper than you know:
dic1 := Dictionary newFrom:{'test' -> 4}.
dic2 := IdentityDictionary newFrom: {'test' copy -> 4}.
dic1 := Dictionary newFrom:{'test' -> 4}.
dic2 := IdentityDictionary newFrom: {'test' copy -> 4}.
dic1 = dic2.
dic2 = dic1.
dic2 = dic1.
Depending on the order, they are equal or inequal.
The bug is caused by Dictionary>>= using a polymorphic type test #isDictionary. Squeak is unaffected: its #= uses a hardcoded class == test. The least disruptive fix I can think of is adding another type test #isIdentityDictionary in Dictionary that returns false but returns true for every identity dictionary class (like SmalllIdentityDictionary). Then only compare the associations if "self isIdentityDictionary = aDictionary isIdentityDictionary".
I will open an issue.
Sent: Friday, October 09, 2015 at 10:51 AM
From: "Henrik Johansen" <[email protected]>
To: "Pharo Development List" <[email protected]>
Subject: Re: [Pharo-dev] hash and Collections
From: "Henrik Johansen" <[email protected]>
To: "Pharo Development List" <[email protected]>
Subject: Re: [Pharo-dev] hash and Collections
It's not.On 09 Oct 2015, at 4:33 , Esteban Lorenzano <[email protected]> wrote:On 09 Oct 2015, at 16:21, Gabriel Cotelli <[email protected]> wrote:If the collection implements = using the objects it holds then you need to consider at least some of them in the hash calculation. I can't conceive a hash calculation for this case independent of the contents (well, just hardcode a number but this will lead to always collide if used as a key in a hashed collection).it is not :)I'm with Levente here, I think the hash implementation is reasonable. And I wouldn't use a mutable object as key in a hashed collection.no idea… I’m not using it, just arrive to that method random and I cannot understand it.I still believe is wrong.
Either Dictionary >> #= or IdentityDictionary >> #species in Pharo *is* broken though.
dic1 := Dictionary newFrom:{1 -> 4}.
dic2 := IdentityDictionary newFrom: dic1 associations .
dic1 = dic2 true
dic1 hash = dic2 hash false
Cheers,
Henry
