IdentitySet>>collect:

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

IdentitySet>>collect:

Eliot Miranda-2
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


Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

timrowledge

On 26-11-2014, at 10:19 AM, Eliot Miranda <[hidden email]> 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)

I think I agree. That looks pretty wrong.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: HEM: Hide Evidence of Malfunction



Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Levente Uzonyi-2
In reply to this post by Eliot Miranda-2
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?

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

>
> WTF??
>
> (IdentitySet withAll: #(1 2 3 1.0 2.0 3.0)) collect: [:e| e] a Set(1.0 2 3)
> --
> best,Eliot
>
>

Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

David T. Lewis
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.

Dave


Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Levente Uzonyi-2
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."

Levente

>
> Dave
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Eliot Miranda-2


On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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


Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Igor Stasenko
i would make an #identityCollect: for sets.
so it is more explicit, and also can be used with any other sets as input.

On 26 November 2014 at 22:56, Eliot Miranda <[hidden email]> wrote:


On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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






--
Best regards,
Igor Stasenko.


Reply | Threaded
Open this post in threaded view
|

AW: [squeak-dev] IdentitySet>>collect:

frank.lesser
In reply to this post by Eliot Miranda-2

hmm, the problem is different IMO,

 

**corrected, but still wrong**

(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]   IdentitySet(1 )

 

collect: should always preserve the size of the original collection so it must return an OrderedCollection !


Von: [hidden email] [mailto:[hidden email]] Im Auftrag von Eliot Miranda
Gesendet: Mittwoch, 26. November 2014 22:57
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] IdentitySet>>collect:

 

 

 

On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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



Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

David T. Lewis
In reply to this post by Eliot Miranda-2
On Wed, Nov 26, 2014 at 01:56:32PM -0800, Eliot Miranda wrote:

> On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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.

Yes. I confused myself by going too far back in the wayback machine.
It seems that in Squeak 2.8 we had this:

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

Which is clearly wrong, as Levente explains above.

Dave

>
> 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.
>




Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Eliot Miranda-2
In reply to this post by frank.lesser


On Wed, Nov 26, 2014 at 2:37 PM, Frank Lesser <[hidden email]> wrote:

hmm, the problem is different IMO,

 

**corrected, but still wrong**

(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]   IdentitySet(1 )

 

collect: should always preserve the size of the original collection so it must return an OrderedCollection !


Since when?  I'm not sure I accept that collect: is one-to-one.  For Sets I wouldn't expect that.
 


Von: [hidden email] [mailto:[hidden email]] Im Auftrag von Eliot Miranda
Gesendet: Mittwoch, 26. November 2014 22:57
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] IdentitySet>>collect:

 

 

 

On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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







--
best,
Eliot


Reply | Threaded
Open this post in threaded view
|

AW: ** SPAM ** Re: [squeak-dev] IdentitySet>>collect:

frank.lesser

Hi Eliiot.

I am not a native English - but collect: means collect IMO.

so for every element deliver the result of evaluating the block. DOT

interesting issue.

Frank


Von: [hidden email] [mailto:[hidden email]] Im Auftrag von Eliot Miranda
Gesendet: Mittwoch, 26. November 2014 23:44
An: The general-purpose Squeak developers list
Betreff: ** SPAM ** Re: [squeak-dev] IdentitySet>>collect:

 

 

 

On Wed, Nov 26, 2014 at 2:37 PM, Frank Lesser <[hidden email]> wrote:

hmm, the problem is different IMO,

 

**corrected, but still wrong**

(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]   IdentitySet(1 )

 

collect: should always preserve the size of the original collection so it must return an OrderedCollection !

 

Since when?  I'm not sure I accept that collect: is one-to-one.  For Sets I wouldn't expect that.

 


Von: [hidden email] [mailto:[hidden email]] Im Auftrag von Eliot Miranda
Gesendet: Mittwoch, 26. November 2014 22:57
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] IdentitySet>>collect:

 

 

 

On Wed, Nov 26, 2014 at 1:26 PM, Levente Uzonyi <[hidden email]> 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





 

--

best,

Eliot



Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

David T. Lewis
On Wed, Nov 26, 2014 at 11:52:43PM +0100, Frank Lesser wrote:
> Hi Eliiot.
>
> I am not a native English - but collect: means collect IMO.
>
> so for every element deliver the result of evaluating the block. DOT
>
> interesting issue.
>
> Frank

I am a native American speaker, so your English is probably better than mine ;-)

I also was surprised by the result. But IdentitySet>>collect: is doing
the right thing in iterating over all the elements of the identity set:

  | r |
  r := Random new.
  ((IdentitySet withAll: #(1 2 3 1.0 2.0 3.0))
      collect: [:e | r next]) size ==> 6


The confusing behavior is the result of answering a Set rather than IdentitySet.

Eliot argues for answering an IdentitySet, Levente explains why this may
not be a good idea, and Eliot agrees that Levente's suggestion of using
the explicit #collect:as: is a satisfactory solution.

Dave


Reply | Threaded
Open this post in threaded view
|

AW: [squeak-dev] IdentitySet>>collect:

frank.lesser
hmm, not convinced

(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
OrderedCollection(1 1 )

in LSWVST ( one-to-one ), you collect results of evaluating a block on
objects.

Frank
maybe I am wrong ...

-----Ursprüngliche Nachricht-----
Von: [hidden email]
[mailto:[hidden email]] Im Auftrag von David
T. Lewis
Gesendet: Donnerstag, 27. November 2014 00:11
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] IdentitySet>>collect:

On Wed, Nov 26, 2014 at 11:52:43PM +0100, Frank Lesser wrote:
> Hi Eliiot.
>
> I am not a native English - but collect: means collect IMO.
>
> so for every element deliver the result of evaluating the block. DOT
>
> interesting issue.
>
> Frank

I am a native American speaker, so your English is probably better than mine
;-)

I also was surprised by the result. But IdentitySet>>collect: is doing
the right thing in iterating over all the elements of the identity set:

  | r |
  r := Random new.
  ((IdentitySet withAll: #(1 2 3 1.0 2.0 3.0))
      collect: [:e | r next]) size ==> 6


The confusing behavior is the result of answering a Set rather than
IdentitySet.

Eliot argues for answering an IdentitySet, Levente explains why this may
not be a good idea, and Eliot agrees that Levente's suggestion of using
the explicit #collect:as: is a satisfactory solution.

Dave



Reply | Threaded
Open this post in threaded view
|

Re: IdentitySet>>collect:

Tobias Pape

On 27.11.2014, at 00:34, Frank Lesser <[hidden email]> wrote:

> hmm, not convinced
>
> (IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
> OrderedCollection(1 1 )
>
> in LSWVST ( one-to-one ), you collect results of evaluating a block on
> objects.
>
> Frank
> maybe I am wrong ...

Where would the order come from for that _Ordered_Collection?

Best
        -Tobias
Reply | Threaded
Open this post in threaded view
|

AW: [squeak-dev] IdentitySet>>collect:

frank.lesser
Hi Tobias,
agree, a problem of "OrderedCollection"
not to break a lot of other things we could return an Array.
but for me collecting has priority.
Frank

-----Ursprüngliche Nachricht-----
Von: [hidden email]
[mailto:[hidden email]] Im Auftrag von Tobias
Pape
Gesendet: Donnerstag, 27. November 2014 00:48
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] IdentitySet>>collect:


On 27.11.2014, at 00:34, Frank Lesser <[hidden email]>
wrote:

> hmm, not convinced
>
> (IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
> OrderedCollection(1 1 )
>
> in LSWVST ( one-to-one ), you collect results of evaluating a block on
> objects.
>
> Frank
> maybe I am wrong ...

Where would the order come from for that _Ordered_Collection?

Best
        -Tobias


Reply | Threaded
Open this post in threaded view
|

Re: AW: [squeak-dev] IdentitySet>>collect:

Levente Uzonyi-2
Your example hides the problem of ordering - what Tobias is asking about - so here's another:

(IdentitySet withAll: #(1 1.0)) collect: [ :each | each class ]

If IdentitySet >> #collect: were returning an Array, then what would be the answer?

{ SmallInteger. Float } or { Float. SmallInteger } ?

If you really want to have the resulting collection have the same size,
but avoid the problem with ordering, then what you really need is a Bag.
Luckily you can have whatever you want (as long as it makes sense):

(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Set.
"==> a Set(1)"
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: IdentitySet.
"==> an IdentitySet(1)"
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Array.
"==> #(1 1)"
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: OrderedCollection.
"==> an OrderedCollection(1 1)."
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Bag.
"==> a Bag(1 1)"
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: IdentityBag.
"==> an IdentityBag(1 1)"
(IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Heap.
"==> a Heap(1 1)"

Levente

On Thu, 27 Nov 2014, Frank Lesser wrote:

> Hi Tobias,
> agree, a problem of "OrderedCollection"
> not to break a lot of other things we could return an Array.
> but for me collecting has priority.
> Frank
>
> -----Ursprüngliche Nachricht-----
> Von: [hidden email]
> [mailto:[hidden email]] Im Auftrag von Tobias
> Pape
> Gesendet: Donnerstag, 27. November 2014 00:48
> An: The general-purpose Squeak developers list
> Betreff: Re: [squeak-dev] IdentitySet>>collect:
>
>
> On 27.11.2014, at 00:34, Frank Lesser <[hidden email]>
> wrote:
>
>> hmm, not convinced
>>
>> (IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
>> OrderedCollection(1 1 )
>>
>> in LSWVST ( one-to-one ), you collect results of evaluating a block on
>> objects.
>>
>> Frank
>> maybe I am wrong ...
>
> Where would the order come from for that _Ordered_Collection?
>
> Best
> -Tobias
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: AW: [squeak-dev] IdentitySet>>collect:

David T. Lewis
It seems to me that Object>>species is intended to handle this sort of issue.

For IdentitySet, it answers what Eliot was expecting:

   IdentitySet new species ==> IdentitySet
   Set new species ==> Set

However, IdentitySet>>collect: does not make use of this, and it answers
a Set for the reasons that Levente explained.

Answering an Array or and OrderedCollection would not really make sense,
because sets are unordered collections (but Bag might be better).

Shouldn't we have an implementation of IdentitySet>>species that answers
Set (or Bag), with a method comment explaining why this is the case, and
with all of the collection methods using #species to answer the right
kind of result?

I note that IdentitySet>>collect: answers a Set, but IdentitySet>select:
sends #species and therefore answers an IdentitySet.

So I think that if we want the #species of an IdentitySet to be a Set,
then we should make it so, and give it a method comment to explain the
rationale. And the #collect: and #select: methods should both answer a
result of that #species.

Dave


On Thu, Nov 27, 2014 at 01:14:30AM +0100, Levente Uzonyi wrote:

> Your example hides the problem of ordering - what Tobias is asking about -
> so here's another:
>
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each class ]
>
> If IdentitySet >> #collect: were returning an Array, then what would be the
> answer?
>
> { SmallInteger. Float } or { Float. SmallInteger } ?
>
> If you really want to have the resulting collection have the same size,
> but avoid the problem with ordering, then what you really need is a Bag.
> Luckily you can have whatever you want (as long as it makes sense):
>
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Set.
> "==> a Set(1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> IdentitySet.
> "==> an IdentitySet(1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> Array.
> "==> #(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> OrderedCollection.
> "==> an OrderedCollection(1 1)."
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Bag.
> "==> a Bag(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> IdentityBag.
> "==> an IdentityBag(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> Heap.
> "==> a Heap(1 1)"
>
> Levente
>
> On Thu, 27 Nov 2014, Frank Lesser wrote:
>
> >Hi Tobias,
> >agree, a problem of "OrderedCollection"
> >not to break a lot of other things we could return an Array.
> >but for me collecting has priority.
> >Frank
> >
> >-----Urspr?ngliche Nachricht-----
> >Von: [hidden email]
> >[mailto:[hidden email]] Im Auftrag von
> >Tobias
> >Pape
> >Gesendet: Donnerstag, 27. November 2014 00:48
> >An: The general-purpose Squeak developers list
> >Betreff: Re: [squeak-dev] IdentitySet>>collect:
> >
> >
> >On 27.11.2014, at 00:34, Frank Lesser <[hidden email]>
> >wrote:
> >
> >>hmm, not convinced
> >>
> >>(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
> >>OrderedCollection(1 1 )
> >>
> >>in LSWVST ( one-to-one ), you collect results of evaluating a block on
> >>objects.
> >>
> >>Frank
> >>maybe I am wrong ...
> >
> >Where would the order come from for that _Ordered_Collection?
> >
> >Best
> > -Tobias
> >

Reply | Threaded
Open this post in threaded view
|

Re: AW: [squeak-dev] IdentitySet>>collect:

Eliot Miranda-2


On Wed, Nov 26, 2014 at 4:31 PM, David T. Lewis <[hidden email]> wrote:
It seems to me that Object>>species is intended to handle this sort of issue.

You're right.  That's what it's there for.

For IdentitySet, it answers what Eliot was expecting:

   IdentitySet new species ==> IdentitySet
   Set new species ==> Set

However, IdentitySet>>collect: does not make use of this, and it answers
a Set for the reasons that Levente explained.

Answering an Array or and OrderedCollection would not really make sense,
because sets are unordered collections (but Bag might be better).

Shouldn't we have an implementation of IdentitySet>>species that answers
Set (or Bag), with a method comment explaining why this is the case, and
with all of the collection methods using #species to answer the right
kind of result?

I note that IdentitySet>>collect: answers a Set, but IdentitySet>select:
sends #species and therefore answers an IdentitySet.

So I think that if we want the #species of an IdentitySet to be a Set,
then we should make it so, and give it a method comment to explain the
rationale. And the #collect: and #select: methods should both answer a
result of that #species.

+1
 
Dave


On Thu, Nov 27, 2014 at 01:14:30AM +0100, Levente Uzonyi wrote:
> Your example hides the problem of ordering - what Tobias is asking about -
> so here's another:
>
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each class ]
>
> If IdentitySet >> #collect: were returning an Array, then what would be the
> answer?
>
> { SmallInteger. Float } or { Float. SmallInteger } ?
>
> If you really want to have the resulting collection have the same size,
> but avoid the problem with ordering, then what you really need is a Bag.
> Luckily you can have whatever you want (as long as it makes sense):
>
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Set.
> "==> a Set(1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> IdentitySet.
> "==> an IdentitySet(1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> Array.
> "==> #(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> OrderedCollection.
> "==> an OrderedCollection(1 1)."
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as: Bag.
> "==> a Bag(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> IdentityBag.
> "==> an IdentityBag(1 1)"
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each asInteger ] as:
> Heap.
> "==> a Heap(1 1)"
>
> Levente
>
> On Thu, 27 Nov 2014, Frank Lesser wrote:
>
> >Hi Tobias,
> >agree, a problem of "OrderedCollection"
> >not to break a lot of other things we could return an Array.
> >but for me collecting has priority.
> >Frank
> >
> >-----Urspr?ngliche Nachricht-----
> >Von: [hidden email]
> >[mailto:[hidden email]] Im Auftrag von
> >Tobias
> >Pape
> >Gesendet: Donnerstag, 27. November 2014 00:48
> >An: The general-purpose Squeak developers list
> >Betreff: Re: [squeak-dev] IdentitySet>>collect:
> >
> >
> >On 27.11.2014, at 00:34, Frank Lesser <[hidden email]>
> >wrote:
> >
> >>hmm, not convinced
> >>
> >>(IdentitySet withAll: #(1 1.0)) collect: [:e| e asInteger ]
> >>OrderedCollection(1 1 )
> >>
> >>in LSWVST ( one-to-one ), you collect results of evaluating a block on
> >>objects.
> >>
> >>Frank
> >>maybe I am wrong ...
> >
> >Where would the order come from for that _Ordered_Collection?
> >
> >Best
> >     -Tobias
> >




--
best,
Eliot


Reply | Threaded
Open this post in threaded view
|

Re: AW: [squeak-dev] IdentitySet>>collect:

Florin Mateoc-4
In reply to this post by Levente Uzonyi-2
On 11/26/2014 7:14 PM, Levente Uzonyi wrote:
> Your example hides the problem of ordering - what Tobias is asking about - so here's another:
>
> (IdentitySet withAll: #(1 1.0)) collect: [ :each | each class ]
>
> If IdentitySet >> #collect: were returning an Array, then what would be the answer?
>
> { SmallInteger. Float } or { Float. SmallInteger } ?
snip
> Levente


Then why does Dictionary>>keys return an Array? Where does the order come from in that example?
Similarly, where does the order come from when you invoke collect:as: on a set with Array as an argument?
The answer is quite simple: it is the iteration order. collect: is part of the _iteration_ protocol.

I agree with Frank here, for me a more important aspect of collect: is preserving the _mapping_ between the original
elements and the collected values.
There is no obvious mapping if there are fewer collected values than elements.

Florin


Reply | Threaded
Open this post in threaded view
|

Re: [Pharo-dev] IdentitySet>>collect:

Marcus Denker-4
In reply to this post by Eliot Miranda-2

> On 26 Nov 2014, at 19:19, Eliot Miranda <[hidden email]> 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)

Yes, I would say so. I think we fixed some others like that already (not 100% sure)

I added an issue tracker entry

14535 IdentitySet>>collect: answers a Set, not an IdentitySet.
        https://pharo.fogbugz.com/f/cases/14535

        Marcus


123