[squeak-dev] Dictionary>>collect: returning OrderedCollection?

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

[squeak-dev] Dictionary>>collect: returning OrderedCollection?

Andreas.Raab
Hi -

Just got bitten by the fact that Dictionary>>collect: returns an
OrderedCollection instead of a Dictionary. What I had expected was e.g.,

   dict := Dictionary newFromPairs:{
        #first.  1.
        #second. 2.
        #third.  3.
   }.
   dict collect:[:item| item asWords].

=>  a Dictionary(#first->'one' #second->'two' #third->'three' )

but instead the result is an OrderedCollection('one' 'two' 'three').
Does anyone besides me consider this a bug? What does ANSI say about
this issue?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

Bert Freudenberg

On 12.06.2008, at 23:21, Andreas Raab wrote:

> Hi -
>
> Just got bitten by the fact that Dictionary>>collect: returns an  
> OrderedCollection instead of a Dictionary. What I had expected was  
> e.g.,
>
>  dict := Dictionary newFromPairs:{
> #first.  1.
> #second. 2.
> #third.  3.
>  }.
>  dict collect:[:item| item asWords].
>
> =>  a Dictionary(#first->'one' #second->'two' #third->'three' )
>
> but instead the result is an OrderedCollection('one' 'two' 'three').  
> Does anyone besides me consider this a bug? What does ANSI say about  
> this issue?


Don't know about ANSI, but I'd have expected a Dictionary, too.

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

Hans-Martin Mosner
In reply to this post by Andreas.Raab
Andreas Raab schrieb:
> Does anyone besides me consider this a bug? What does ANSI say about
> this issue?
I think that #collect: should be in line with #select: and #reject:
which both return Dictionaries.
One possible reason why #collect returns a different kind of collection
is that for some base collections, the results of the block might not
fit (for example, "aByteArray collect: [:x | x odd]" would raise an
exception).
Incidentally, VisualWorks behaves as you and I expect.

Cheers,
Hans-Martin

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Nicolas Cellier-3
Hans-Martin Mosner a écrit :
> Andreas Raab schrieb:
>> Does anyone besides me consider this a bug? What does ANSI say about
>> this issue?
> I think that #collect: should be in line with #select: and #reject:
> which both return Dictionaries.

Agree, I fully support Andreas request as a very logical one.

Beside, it is very easy to get an OrederedCollection if that is really
wanted in Squeak:
     (dict collect:[:item| item asWords]) asOrderedCollection.

or:
     dict values collect:[:item| item asWords]

> One possible reason why #collect returns a different kind of collection
> is that for some base collections, the results of the block might not
> fit (for example, "aByteArray collect: [:x | x odd]" would raise an
> exception).

True, but since Dictionary can hold any arbitrary value...
I think that historical reason is that #do: only iterates on values, and
that super #collect: was implemented with a #do: loop...
And long ago, values would answer a Bag because Dictionary keys are
unordered (I guess Dictionary species would ^Bag, but no old image here
to check...)

> Incidentally, VisualWorks behaves as you and I expect.
>

Only recently, because 7.2 did still return an OrderedCollection...


> Cheers,
> Hans-Martin
>
>

Nicolas


Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Louis LaBrunda
In reply to this post by Andreas.Raab
Hi,

VA Smalltalk returns a Dictionary.  Returning a Dictionary makes sense, as you
can always get an OrderedCollection with:

        dict values collect: [:item| item asWords].

forcing a Dictionary from what Squeak does for #collect:, is probably not so
easy.

Lou

>Just got bitten by the fact that Dictionary>>collect: returns an
>OrderedCollection instead of a Dictionary. What I had expected was e.g.,
>
>   dict := Dictionary newFromPairs:{
> #first.  1.
> #second. 2.
> #third.  3.
>   }.
>   dict collect:[:item| item asWords].
>
>=>  a Dictionary(#first->'one' #second->'two' #third->'three' )
>
>but instead the result is an OrderedCollection('one' 'two' 'three').
>Does anyone besides me consider this a bug? What does ANSI say about
>this issue?
>
>Cheers,
>   - Andreas
>
-----------------------------------------------------------
Louis LaBrunda
Keystone Software Corp.
SkypeMe callto://PhotonDemon
mailto:[hidden email] http://www.Keystone-Software.com


Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Andreas.Raab
In reply to this post by Hans-Martin Mosner
Thanks everyone. I filed a bug and a fix at

   http://bugs.squeak.org/view.php?id=7095

BTW, Josh pointed out that ANSI agrees with that definition too:

5.7.2.6 Message Refinement: collect: transformer
Synopsis
Answer a new collection constructed by gathering the results of
evaluating transformer with each element of the receiver.

Definition: <collection>
For each element of the receiver, transformer is evaluated with the
element as the parameter. The results of these evaluations are collected
into a new collection. The elements are traversed in the order specified
by the #do: message for the receiver. Unless specifically refined, this
message is defined to answer an object conforming to the same protocol
as the receiver.

Refinement: <abstractDictionary>
Answer a new instance of the receiver's type with the same keys. For
each key of the answer, a new element is obtained by evaluating
transformer with the corresponding element of the receiver as the parameter.

Cheers,
   - Andreas

Hans-Martin Mosner wrote:

> Andreas Raab schrieb:
>> Does anyone besides me consider this a bug? What does ANSI say about
>> this issue?
> I think that #collect: should be in line with #select: and #reject:
> which both return Dictionaries.
> One possible reason why #collect returns a different kind of collection
> is that for some base collections, the results of the block might not
> fit (for example, "aByteArray collect: [:x | x odd]" would raise an
> exception).
> Incidentally, VisualWorks behaves as you and I expect.
>
> Cheers,
> Hans-Martin
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
In reply to this post by Hans-Martin Mosner
On Friday 13 Jun 2008 3:02:34 am Hans-Martin Mosner wrote:
> Andreas Raab schrieb:
> > Does anyone besides me consider this a bug? What does ANSI say about
> > this issue?
>
> I think that #collect: should be in line with #select: and #reject:
> which both return Dictionaries.
Why so? #collect; is a closed operation on Collection, not on Dictionary.
Unlike #select: or #reject:, it aggregates new objects (String in the
example) generated from the values (Integer). Key associated with the value
will not carry over to the new object automatically.

Bluebook describes collect: aBlock as:
<quote>
Evaluate the argument, aBlock, for each of the receiver's elements. Answer a
new collection like that of the receiver containing the value returned by the
block on each evaluation.
....
Messages inherited from the class Collection -- includes:, do: and other
enumeration messages -- are applied to the *values* of the Dictionary. That
is, these messages refer to the values of each association in the Dictionary,
rather than to the keys or to the associations themselves.
</quote>

Subbu

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Nicolas Cellier-3
K. K. Subramaniam a écrit :

> On Friday 13 Jun 2008 3:02:34 am Hans-Martin Mosner wrote:
>> Andreas Raab schrieb:
>>> Does anyone besides me consider this a bug? What does ANSI say about
>>> this issue?
>> I think that #collect: should be in line with #select: and #reject:
>> which both return Dictionaries.
> Why so? #collect; is a closed operation on Collection, not on Dictionary.
> Unlike #select: or #reject:, it aggregates new objects (String in the
> example) generated from the values (Integer). Key associated with the value
> will not carry over to the new object automatically.
>
> Bluebook describes collect: aBlock as:
> <quote>
> Evaluate the argument, aBlock, for each of the receiver's elements. Answer a
> new collection like that of the receiver containing the value returned by the
> block on each evaluation.
> ....
> Messages inherited from the class Collection -- includes:, do: and other
> enumeration messages -- are applied to the *values* of the Dictionary. That
> is, these messages refer to the values of each association in the Dictionary,
> rather than to the keys or to the associations themselves.
> </quote>
>
> Subbu
>
>

 From historical POV, you are right, but...

With all the respect due to the holly blue book and its authors, it is
not the bible.

Viewing a Dictionary as a Bag of values certainly was a simple way to
define a compatible Behavior with other collections.

However, it's a much too reductive view that is loosing the Dictionary
spirit. The spirit is associated to the keys undoubtedly.

Let's adopt a more useful behaviour preserving the keys.

And good news, if a Dictionary can be viewed as a Bag of Values, then
collected key/value associations can still be viewed as a Bag of
values... So you don't loose anything, you can still ask for includes:
do: and other Bag-compatible protocol... you only win some associated keys!

Cheers

Nicolas


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
On Friday 13 Jun 2008 5:38:37 pm nicolas cellier wrote:
> With all the respect due to the holly blue book and its authors, it is
> not the bible.
Sorry, I didn't mean to throw the book at you. I only quoted the passage to
point out that collect: is WAD.

That doesn't stop us from adding a new method to create a new dictionary by
mapping values from an existing dict without affecting its keys. E.g.
        numberDictionary associationsCollect: [ :v | v asWords ].

Here is my first cut at it:

associationsCollect: aBlock
        | d |
        d = WriteStream on: (Array new: self size).
        self associationsDo: [ :assoc | d nextPut: assoc key -> (aBlock value: assoc
value) ].
        ^Dictionary newFrom: d contents

Subbu

Reply | Threaded
Open this post in threaded view
|

RE: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

Joerg Beekmann, DeepCove Labs (YVR)
In reply to this post by Andreas.Raab
I believe ANSI says it should be a dictionary. VW has just changed their
implementation in version 7.6 to return a Dictionary.

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of
Andreas Raab
Sent: Thursday, June 12, 2008 2:22 PM
To: The general-purpose Squeak developers list
Subject: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

Hi -

Just got bitten by the fact that Dictionary>>collect: returns an
OrderedCollection instead of a Dictionary. What I had expected was e.g.,

   dict := Dictionary newFromPairs:{
        #first.  1.
        #second. 2.
        #third.  3.
   }.
   dict collect:[:item| item asWords].

=>  a Dictionary(#first->'one' #second->'two' #third->'three' )

but instead the result is an OrderedCollection('one' 'two' 'three').
Does anyone besides me consider this a bug? What does ANSI say about
this issue?

Cheers,
   - Andreas


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Dictionary>>collect: returning OrderedCollection?

timrowledge
Dictionary>do: etc work on the values of the associations. #collect:  
should continue the pattern. #associationsDo: etc exist if you need to  
work with the associations.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Artificial Intelligence:  Making computers behave like they do in the  
movies.



Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Nicolas Cellier-3
tim Rowledge a écrit :

> Dictionary>do: etc work on the values of the associations. #collect:
> should continue the pattern. #associationsDo: etc exist if you need to
> work with the associations.
>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> Artificial Intelligence:  Making computers behave like they do in the
> movies.
>

Hi tim and Subbu,
you follow a certain historical logic.
But behaviour could be much simpler and homogeneous with ANSI POV.
Consider current state of Squeak:

1) select: and reject: already return a Dictionary
2) collect: current implementation would answer an OrderedCollection
which is a nonsense for these reasons:

- there is no reason that values be Ordered since keys are not
- depending on Dictionary allocated size, the order will just change
- answering an OrderedCollection is equivalent to associating integer
keys to values in an arbitrary random order...

Original st-80 logic would have been to answer a Bag, nothing else.

3) Since Dictionary can answer most of Bag protocol transparently, you
won't even notice the change if collect: answers a Dictionary. This is a
transparent operation
Changing collect: does absolutely not change the fact that Dictionary
can be viewed as a Collection of values...

I vote against this un-necessary associationsCollect:

Nicolas


Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Paolo Bonzini-2
In reply to this post by Nicolas Cellier-3

>> Messages inherited from the class Collection -- includes:, do: and
>> other enumeration messages -- are applied to the *values* of the
>> Dictionary. That is, these messages refer to the values of each
>> association in the Dictionary, rather than to the keys or to the
>> associations themselves.
>
> With all the respect due to the holly blue book and its authors,
> it is not the bible.

Actually, the "modern" view of Dictionary as a "keyed collection with
external keys" (external = given by the user) does not conflict at all
with the blue book definition.  Like #do:, #collect: only works on the
values -- but like on the other keyed collections, i.e.
SequenceableCollections, the keys are preserved.

 From here, one can define by extension the obvious meaning of #select:
and #reject: for a dictionary.  Note that this meaning is different
between sequenceable collections and dictionaries, because answering
false (resp. true) will change the keys of all subsequent values in a
sequenceable collection!

Note that this:

> associationsCollect: aBlock
> ...
> self associationsDo: [ :assoc | d nextPut: assoc key -> (aBlock value: assoc
               value) ].

would be very wrong, because associationsSomething: messages work on
associations, while your message passes only the value to the block.  An
hypothetical associationsCollect: would do

associationsCollect: aBlock
        | d |
        d := Dictionary new.
        self associationsDo: [ :assoc | d add: (aBlock value: assoc) ]

and I have nothing against it. :-)

Paolo

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
In reply to this post by Nicolas Cellier-3
On Saturday 14 Jun 2008 12:36:54 am nicolas cellier wrote:

> tim Rowledge a écrit :
> > Dictionary>do: etc work on the values of the associations. #collect:
> > should continue the pattern. #associationsDo: etc exist if you need to
> > work with the associations.
> >
> > tim
> > --
> > tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> > Artificial Intelligence:  Making computers behave like they do in the
> > movies.
>
> Hi tim and Subbu,
> you follow a certain historical logic.
> But behaviour could be much simpler and homogeneous with ANSI POV.
ANSI v1.9 [1] treats collect: as a transformer and only requires it to return
a collection. Returning a dictionary is a permitted 'refinement'.

> Consider current state of Squeak:
>
> 1) select: and reject: already return a Dictionary
This is a non-sequitur. select:/reject: are discriminators while collect: is a
transformer.

> Original st-80 logic would have been to answer a Bag, nothing else.
:-/. In ST-80, Dictionary isa Set isa Collection while Bag isa Collection. You
meant a Set, perhaps?

[1] http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf

Subbu

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
In reply to this post by Paolo Bonzini-2
On Saturday 14 Jun 2008 6:03:34 am Paolo Bonzini wrote:

> > associationsCollect: aBlock
> >       ...
> >       self associationsDo: [ :assoc | d nextPut: assoc key -> (aBlock
> > value: assoc
>
>                value) ].
>
> would be very wrong, because associationsSomething: messages work on
> associations, while your message passes only the value to the block.  An
> hypothetical associationsCollect: would do
>
> associationsCollect: aBlock
>         | d |
>         d := Dictionary new.
>         self associationsDo: [ :assoc | d add: (aBlock value: assoc) ]
I did write it this way initially but then it appeared like an overkill to me
as we are not changing the keys, only replacing the values associated with
the keys.

Now we have three ways of defining collect: on a dictionary - values alone,  
on the value part of associations, and on associations.

Subbu

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Bert Freudenberg

On 14.06.2008, at 08:26, K. K. Subramaniam wrote:

> On Saturday 14 Jun 2008 6:03:34 am Paolo Bonzini wrote:
>>> associationsCollect: aBlock
>>>       ...
>>>       self associationsDo: [ :assoc | d nextPut: assoc key ->  
>>> (aBlock
>>> value: assoc
>>
>>                value) ].
>>
>> would be very wrong, because associationsSomething: messages work on
>> associations, while your message passes only the value to the  
>> block.  An
>> hypothetical associationsCollect: would do
>>
>> associationsCollect: aBlock
>>         | d |
>>         d := Dictionary new.
>>         self associationsDo: [ :assoc | d add: (aBlock value:  
>> assoc) ]
> I did write it this way initially but then it appeared like an  
> overkill to me
> as we are not changing the keys, only replacing the values  
> associated with
> the keys.
>
> Now we have three ways of defining collect: on a dictionary - values  
> alone,
> on the value part of associations, and on associations.


Shouldn't "associationsCollect:" be equivalent to "associations  
collect:"?

- Bert -



Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Nicolas Cellier-3
In reply to this post by K. K. Subramaniam
K. K. Subramaniam a écrit :

> On Saturday 14 Jun 2008 12:36:54 am nicolas cellier wrote:
>> tim Rowledge a écrit :
>>> Dictionary>do: etc work on the values of the associations. #collect:
>>> should continue the pattern. #associationsDo: etc exist if you need to
>>> work with the associations.
>>>
>>> tim
>>> --
>>> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
>>> Artificial Intelligence:  Making computers behave like they do in the
>>> movies.
>> Hi tim and Subbu,
>> you follow a certain historical logic.
>> But behaviour could be much simpler and homogeneous with ANSI POV.
> ANSI v1.9 [1] treats collect: as a transformer and only requires it to return
> a collection. Returning a dictionary is a permitted 'refinement'.
>
>> Consider current state of Squeak:
>>
>> 1) select: and reject: already return a Dictionary
> This is a non-sequitur. select:/reject: are discriminators while collect: is a
> transformer.
>
>> Original st-80 logic would have been to answer a Bag, nothing else.
> :-/. In ST-80, Dictionary isa Set isa Collection while Bag isa Collection. You
> meant a Set, perhaps?
>
> [1] http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf
>

No, I mean Bag.
Dictionary keys are a Set, but values don't have to be unique.
If you have the blue book or a st80 available, check what values was
originally returning.

> Subbu
>
>


Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

Paolo Bonzini-2
In reply to this post by K. K. Subramaniam

> Now we have three ways of defining collect: on a dictionary - values alone,  
> on the value part of associations, and on associations.

Associations are just an implementation detail.  Dictionaries are just
collections of values with an externally-defined keys.

Paolo

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
In reply to this post by Bert Freudenberg
On Saturday 14 Jun 2008 3:02:03 pm Bert Freudenberg wrote:
> Shouldn't "associationsCollect:" be equivalent to "associations  
> collect:"?

If both key and its value are being transformed by aBlock, yes. If only the
values are being changed with the keys remaining same (e.g. translating
english words to french) then we could avoid key lookups for every add.

Subbu

Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Dictionary>>collect: returning OrderedCollection?

K. K. Subramaniam
In reply to this post by Nicolas Cellier-3
On Saturday 14 Jun 2008 11:50:27 pm nicolas cellier wrote:
> No, I mean Bag.
> Dictionary keys are a Set, but values don't have to be unique.
> If you have the blue book or a st80 available, check what values was
> originally returning.

Ha, I see what you mean. The values of a Dictionary are indeed a Bag.
I got confused because the original poster was expecting to retain the keys in
the result. Perhaps, I should cut down on my late night sessions :-).

Thank you for your patience,
Subbu