Dictionary>>addAll:

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

Dictionary>>addAll:

Andreas.Raab
Hm ... tell me what you *think* this code would do:

   dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.

then run it. Does that seem right to you?

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Nicolas Cellier
You mean you'd like to use associationsDo: like in Dictionary class>newFrom: ?
OK, it would work both for a list of associations and a Dictionary argument.

Con: IMHO Collection>>associationsDo: is a tricky hack, and I don't like it.
Pro: since the trick is already in use, Squeak behaviour would be a
bit more homogeneous and less surprising.

Nicolas

2010/8/24 Andreas Raab <[hidden email]>:

> Hm ... tell me what you *think* this code would do:
>
>  dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>
> then run it. Does that seem right to you?
>
> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Bert Freudenberg
I always use

        {'foo' -> 'bar'. 'hello' -> 'world'} as: Dictionary

so I haven't run into that problem ...

I'm not sure tinkering with Dictionary>>addAll: is a good idea. It certainly is counter-intuitive, but consistent.

- Bert -

On 24.08.2010, at 09:46, Nicolas Cellier wrote:

> You mean you'd like to use associationsDo: like in Dictionary class>newFrom: ?
> OK, it would work both for a list of associations and a Dictionary argument.
>
> Con: IMHO Collection>>associationsDo: is a tricky hack, and I don't like it.
> Pro: since the trick is already in use, Squeak behaviour would be a
> bit more homogeneous and less surprising.
>
> Nicolas
>
> 2010/8/24 Andreas Raab <[hidden email]>:
>> Hm ... tell me what you *think* this code would do:
>>
>>  dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>>
>> then run it. Does that seem right to you?
>>
>> Cheers,
>>  - Andreas
>>
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Levente Uzonyi-2
In reply to this post by Andreas.Raab
On Mon, 23 Aug 2010, Andreas Raab wrote:

> Hm ... tell me what you *think* this code would do:
>
>  dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>
> then run it. Does that seem right to you?

Yes and no. :) Dictionary >> #addAll: expects a "KeyedCollection" as
argument. Array is a "KeyedCollection" with integer keys.
But one could expect that #addAll: works like #add: which is not the case.
We could change #addAll: to use #associationsDo: instead of
#keysAndValueesDo: as Nicolas said, but it might break some code.
If you just want to build a Dictionary from an Array of Associations, then
#newFrom: does what you need (it uses the #associationsDo: trick).


Levente

>
> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Andreas.Raab
On 8/24/2010 2:50 AM, Levente Uzonyi wrote:

> On Mon, 23 Aug 2010, Andreas Raab wrote:
>
>> Hm ... tell me what you *think* this code would do:
>>
>> dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>>
>> then run it. Does that seem right to you?
>
> Yes and no. :) Dictionary >> #addAll: expects a "KeyedCollection" as
> argument. Array is a "KeyedCollection" with integer keys.
> But one could expect that #addAll: works like #add: which is not the case.
> We could change #addAll: to use #associationsDo: instead of
> #keysAndValueesDo: as Nicolas said, but it might break some code.

I cannot really imagine which code that would break. Assuming that
you've got a dictionary would you really use, i.e., aDictionary addAll:
#('hello' 'world') and expect the result to be 1 -> 'hello' and 2 ->
'world'? This was *totally* unexpected for me and at first I couldn't
even understand what was going wrong until I realized that the usage of
#withAll: caused it.

So yes, I think we should fix that to ensure that #addAll: is consistent
with #add: as it is in all other collection types.

> If you just want to build a Dictionary from an Array of Associations,
> then #newFrom: does what you need (it uses the #associationsDo: trick).

Yes, both #newFrom: and #as: appear to do the trick - the above is more
about consistency and least surprises.

Cheers,
   - Andreas

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Nicolas Cellier
2010/8/24 Andreas Raab <[hidden email]>:

> On 8/24/2010 2:50 AM, Levente Uzonyi wrote:
>>
>> On Mon, 23 Aug 2010, Andreas Raab wrote:
>>
>>> Hm ... tell me what you *think* this code would do:
>>>
>>> dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>>>
>>> then run it. Does that seem right to you?
>>
>> Yes and no. :) Dictionary >> #addAll: expects a "KeyedCollection" as
>> argument. Array is a "KeyedCollection" with integer keys.
>> But one could expect that #addAll: works like #add: which is not the case.
>> We could change #addAll: to use #associationsDo: instead of
>> #keysAndValueesDo: as Nicolas said, but it might break some code.
>
> I cannot really imagine which code that would break. Assuming that you've
> got a dictionary would you really use, i.e., aDictionary addAll: #('hello'
> 'world') and expect the result to be 1 -> 'hello' and 2 -> 'world'? This was
> *totally* unexpected for me and at first I couldn't even understand what was
> going wrong until I realized that the usage of #withAll: caused it.
>
> So yes, I think we should fix that to ensure that #addAll: is consistent
> with #add: as it is in all other collection types.
>
>> If you just want to build a Dictionary from an Array of Associations,
>> then #newFrom: does what you need (it uses the #associationsDo: trick).
>
> Yes, both #newFrom: and #as: appear to do the trick - the above is more
> about consistency and least surprises.
>
> Cheers,
>  - Andreas
>

Agree with Andreas: it's better having addAll: consistent with add:
as: and newFrom: rather than consistent with keysAndValuesDo: (reusing
the keys of a SequenceableCollection), as the later is much probably
unused.

BTW, Dictionary comment deserve a refactoring. I suggest something like

A Dictionary is an unordered collection of values which are indexed by
arbitrary keys.
A Dictionary is thus accessed via #at: and #at:put: messages like
SequenceableCollection, but with arbitrary keys instead of an integer
rank.
The keys can be any object that responds to =.
If the key is absent, #at: raises an Error. An alternate block of code
can be executed and its value returned in this case using
#at:ifAbsent: (see also #at:ifAbsentPut:).
If the key is absent, #at:put: adds a new entry to the Dictionary.
Each key is unique: storing another value with #at:put: at an already
used key overwrites previously associated value.
The values are not necessarily unique, thus a Dictionary can also be
seen as a sort of Bag with this respect.

Dictionary is implemented as a HashedCollection of Association (a
value is associated to its key).
Being a HashedCollection enables fast random access indexed by keys.
Consequently, keys must respond to #hash (see super).

It is possible to grow or shrink a Dictionary using the messages #add:
and #remove: with an Association parameter, however the prefered way
to do so is using #at:put: and #removeKey:.

Enumerating a Dictionary with #do: will only enumerate the values, not the keys.
For enumerating keys and values, use #keysAndValuesDo:, or use
#associationsDo: to enumerate the associations.
#select: #reject: #collect: will operate on values while preserving
the keys and thus answer a new Dictionary.

The keys and values of a Dictionary can be extracted by sending #keys
and #values message.
Though the keys are theoretically a Set and values a Bag, for
efficiency reasons, these messages will both return an Array of keys
and an Array of values. A neat feature is that these messages are
preserving the arbitrary storage order - in other words, (aDictionary
values at: 3) is the value associated to key (aDictionary keys at: 3).

Nicolas

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Hannes Hirzel
On 8/24/10, Nicolas Cellier <[hidden email]> wrote:
[...snip....]

> BTW, Dictionary comment deserve a refactoring. I suggest something like
>
> A Dictionary is an unordered collection of values which are indexed by
> arbitrary keys.
> A Dictionary is thus accessed via #at: and #at:put: messages like
> SequenceableCollection, but with arbitrary keys instead of an integer
> rank.
> The keys can be any object that responds to =.
> If the key is absent, #at: raises an Error. An alternate block of code
> can be executed and its value returned in this case using
> #at:ifAbsent: (see also #at:ifAbsentPut:).
> If the key is absent, #at:put: adds a new entry to the Dictionary.
> Each key is unique: storing another value with #at:put: at an already
> used key overwrites previously associated value.
> The values are not necessarily unique, thus a Dictionary can also be
> seen as a sort of Bag with this respect.
>
> Dictionary is implemented as a HashedCollection of Association (a
> value is associated to its key).
> Being a HashedCollection enables fast random access indexed by keys.
> Consequently, keys must respond to #hash (see super).
>
> It is possible to grow or shrink a Dictionary using the messages #add:
> and #remove: with an Association parameter, however the prefered way
> to do so is using #at:put: and #removeKey:.
>
> Enumerating a Dictionary with #do: will only enumerate the values, not the
> keys.
> For enumerating keys and values, use #keysAndValuesDo:, or use
> #associationsDo: to enumerate the associations.
> #select: #reject: #collect: will operate on values while preserving
> the keys and thus answer a new Dictionary.
>
> The keys and values of a Dictionary can be extracted by sending #keys
> and #values message.
> Though the keys are theoretically a Set and values a Bag, for
> efficiency reasons, these messages will both return an Array of keys
> and an Array of values. A neat feature is that these messages are
> preserving the arbitrary storage order - in other words, (aDictionary
> values at: 3) is the value associated to key (aDictionary keys at: 3).
>
> Nicolas
>
>
 I second this comment change.

--Hannes

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Levente Uzonyi-2
In reply to this post by Andreas.Raab


On Tue, 24 Aug 2010, Andreas Raab wrote:

> On 8/24/2010 2:50 AM, Levente Uzonyi wrote:
>> On Mon, 23 Aug 2010, Andreas Raab wrote:
>>
>>> Hm ... tell me what you *think* this code would do:
>>>
>>> dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>>>
>>> then run it. Does that seem right to you?
>>
>> Yes and no. :) Dictionary >> #addAll: expects a "KeyedCollection" as
>> argument. Array is a "KeyedCollection" with integer keys.
>> But one could expect that #addAll: works like #add: which is not the case.
>> We could change #addAll: to use #associationsDo: instead of
>> #keysAndValueesDo: as Nicolas said, but it might break some code.
>
> I cannot really imagine which code that would break. Assuming that you've got
> a dictionary would you really use, i.e., aDictionary addAll: #('hello'
> 'world') and expect the result to be 1 -> 'hello' and 2 -> 'world'? This was
> *totally* unexpected for me and at first I couldn't even understand what was
> going wrong until I realized that the usage of #withAll: caused it.

This method is from 2003, so there may be code out there which expects
this behavior, even unintentionally.

>
> So yes, I think we should fix that to ensure that #addAll: is consistent with
> #add: as it is in all other collection types.

Ok.


Levente

>
>> If you just want to build a Dictionary from an Array of Associations,
>> then #newFrom: does what you need (it uses the #associationsDo: trick).
>
> Yes, both #newFrom: and #as: appear to do the trick - the above is more about
> consistency and least surprises.
>
> Cheers,
>  - Andreas
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary>>addAll:

Levente Uzonyi-2
In reply to this post by Nicolas Cellier
On Tue, 24 Aug 2010, Nicolas Cellier wrote:

> 2010/8/24 Andreas Raab <[hidden email]>:
>> On 8/24/2010 2:50 AM, Levente Uzonyi wrote:
>>>
>>> On Mon, 23 Aug 2010, Andreas Raab wrote:
>>>
>>>> Hm ... tell me what you *think* this code would do:
>>>>
>>>> dict := Dictionary withAll: {'foo' -> 'bar'. 'hello' -> 'world'}.
>>>>
>>>> then run it. Does that seem right to you?
>>>
>>> Yes and no. :) Dictionary >> #addAll: expects a "KeyedCollection" as
>>> argument. Array is a "KeyedCollection" with integer keys.
>>> But one could expect that #addAll: works like #add: which is not the case.
>>> We could change #addAll: to use #associationsDo: instead of
>>> #keysAndValueesDo: as Nicolas said, but it might break some code.
>>
>> I cannot really imagine which code that would break. Assuming that you've
>> got a dictionary would you really use, i.e., aDictionary addAll: #('hello'
>> 'world') and expect the result to be 1 -> 'hello' and 2 -> 'world'? This was
>> *totally* unexpected for me and at first I couldn't even understand what was
>> going wrong until I realized that the usage of #withAll: caused it.
>>
>> So yes, I think we should fix that to ensure that #addAll: is consistent
>> with #add: as it is in all other collection types.
>>
>>> If you just want to build a Dictionary from an Array of Associations,
>>> then #newFrom: does what you need (it uses the #associationsDo: trick).
>>
>> Yes, both #newFrom: and #as: appear to do the trick - the above is more
>> about consistency and least surprises.
>>
>> Cheers,
>>  - Andreas
>>
>
> Agree with Andreas: it's better having addAll: consistent with add:
> as: and newFrom: rather than consistent with keysAndValuesDo: (reusing
> the keys of a SequenceableCollection), as the later is much probably
> unused.
>
> BTW, Dictionary comment deserve a refactoring. I suggest something like
Indeed.

>
> A Dictionary is an unordered collection of values which are indexed by
> arbitrary keys.
> A Dictionary is thus accessed via #at: and #at:put: messages like
> SequenceableCollection, but with arbitrary keys instead of an integer
> rank.
> The keys can be any object that responds to =.
> If the key is absent, #at: raises an Error. An alternate block of code
> can be executed and its value returned in this case using
> #at:ifAbsent: (see also #at:ifAbsentPut:).
> If the key is absent, #at:put: adds a new entry to the Dictionary.
> Each key is unique: storing another value with #at:put: at an already
> used key overwrites previously associated value.
> The values are not necessarily unique, thus a Dictionary can also be
> seen as a sort of Bag with this respect.
>
> Dictionary is implemented as a HashedCollection of Association (a
> value is associated to its key).
> Being a HashedCollection enables fast random access indexed by keys.
> Consequently, keys must respond to #hash (see super).
>
> It is possible to grow or shrink a Dictionary using the messages #add:
> and #remove: with an Association parameter, however the prefered way
> to do so is using #at:put: and #removeKey:.
>
> Enumerating a Dictionary with #do: will only enumerate the values, not the keys.
> For enumerating keys and values, use #keysAndValuesDo:, or use
> #associationsDo: to enumerate the associations.
> #select: #reject: #collect: will operate on values while preserving
> the keys and thus answer a new Dictionary.
>
> The keys and values of a Dictionary can be extracted by sending #keys
> and #values message.
> Though the keys are theoretically a Set and values a Bag, for
> efficiency reasons, these messages will both return an Array of keys
> and an Array of values. A neat feature is that these messages are
> preserving the arbitrary storage order - in other words, (aDictionary
> values at: 3) is the value associated to key (aDictionary keys at: 3).
Looks good. Maybe a line about that the keys shouldn't change (from #hash
and #= POV) while the dictionary contains them could be useful.


Levente

>
> Nicolas
>
>