[squeak-dev] Re: Dictionary>>addAll:

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Tue Aug 24 16:05:17 UTC 2010


2010/8/24 Andreas Raab <andreas.raab at gmx.de>:
> 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



More information about the Squeak-dev mailing list