[squeak-dev] IdentitySet>>collect:

Eliot Miranda eliot.miranda at gmail.com
Wed Nov 26 21:56:32 UTC 2014


On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <leves at elte.hu> wrote:

> On Wed, 26 Nov 2014, David T. Lewis wrote:
>
>  On Wed, Nov 26, 2014 at 08:01:49PM +0100, Levente Uzonyi wrote:
>>
>>> On Wed, 26 Nov 2014, Eliot Miranda wrote:
>>>
>>>  Hi All,
>>>> ? ? IdentitySet>>collect: answers a Set, not an IdentitySet.? Anyone
>>>> else
>>>> agree this is a serious bug?? Anyone else disagree?
>>>>
>>>> WTF??
>>>>
>>>> (IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [:e| e] a Set(1.0
>>>> 2 3)
>>>> --
>>>> best,Eliot
>>>>
>>>>
>>> Sometimes it's feasable to return an IdentitySet, other times it's not,
>>> so
>>> there's no optimal solution - #collect: can't cover all cases.
>>>
>>> Set >> #collect: explicitly returns a Set, because this is the least bad
>>> solution to handle all of its subclasses reasonably well.
>>> In case of WeakSet, returning a WeakSet makes no sense, because some of
>>> your objects will disappear immediately.
>>> In case of IdentitySet, PluggableSet, KeyedSet and KeyedIdentitySet the
>>> returned values may not behave well in the original collection.
>>>
>>> The best is to always be explicit:
>>>
>>> (IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [ :e | e ] as:
>>> IdentitySet
>>> "==> an IdentitySet(1 2 3 1.0 2.0 3.0)"
>>>
>>> Levente
>>>
>>>
>> In Squeak 2.8 (checked on http://bertfreudenberg.github.io/SqueakJS/run/
>> ):
>>
>>  (IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [:e| e] ==> a
>> Set(2.0 1 2 3 3.0 1.0)
>>
>>
>> But in trunk I get this:
>>
>>  (IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [:e| e] ==> a Set(1
>> 2 3)
>>
>>
>> So answering a Set makes sense for the reasons that Levente explains, but
>> trunk
>> is definitely broken WRT the contents of that set.
>>
>> This bug needs a unit test to go along with whatever fix we agree on.
>>
>
> It's not a bug either. The Floats are not there, because they are equal to
> the integers:
>
> 1 = 1.0 "==> true"
> 1.0 = 1 "==> true"
>
> Therefore they have the same hash:
>
> 1 hash "==> 1"
> 1.0 hash "==> 1"
>
> The bug was in Squeak 2.8:
> 1.0 = 1 "==> true"
> 1 = 1.0 "==> true"
> 1 hash "==> 1"
> 1.0 hash "==> 61440"
>
> Here's the comment of Float >> hash from The Trunk:
>         "Hash is reimplemented because = is implemented. Both words of the
> float are used. (The bitShift:'s ensure that the intermediate results do
> not become a large integer.) Care is taken to answer same hash as an equal
> Integer."
>

Exactly.

My hope would be something like this (Set order is arbitrary)

        ((IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [:e| e]) =>
IdentitySet (1 2 3 1.0 2.0 3.0)

but that
       (Set withAll: #(1 2 3 1.0 2.0 3.0)) => Set (1 2 3)

(and it always contains just the integers since these are added first).

But Levente's collect:as: solution is perfectly acceptable and as he points
out has the advantage of being explicit.


> Levente
>
>
>> Dave
>>
>>
>>
>>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20141126/58279cf9/attachment.htm


More information about the Squeak-dev mailing list