Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

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

Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer
Is anyone else bother by this inconsistency?


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer




---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer  wrote ----

>Is anyone else bother[ed] by this inconsistency?

Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary and updates SmallDictionary's implementations of those messages to return the same value - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and #remove:ifAbsent: returning the key of the removed association. The second package adds #testRemove and #testRemoveIfAbsent to DictionaryTest (through a trait).


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Igor Stasenko
On 6 December 2010 23:52, jaayer <[hidden email]> wrote:

>
>
>
>
> ---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer  wrote ----
>
>>Is anyone else bother[ed] by this inconsistency?
>
> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary and updates SmallDictionary's implementations of those messages to return the same value - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and #remove:ifAbsent: returning the key of the removed association. The second package adds #testRemove and #testRemoveIfAbsent to DictionaryTest (through a trait).
>
>

Hello, jaayer.

The point about Dictionary inconsistency was raised multiple times before.
I was among ones of those who did that couple of years ago.
What can i say?
While it is much better to have consistency,
in fact it doesn't really changes much. I don't think that #remove: in
a form you proposed will be any userful.
I would really keep it simply #shouldNotImplement , because it is
unclear what is a least surprising behavior of this method for
Dictionary.
One might argue, that its more userful to make it same as #removeKey:,
other one could point that its should be symmetrical to #add: ,
but hey, then #do: should be also symmetrical to #add: , isnt? And so
it should iterate over associations , not just values. So, it is a can
of worms, once you open it , you can never finish the endless
discussions :)
It is just works in a way how we like (defined). It is like an
imaginary numbers in math where  sqrt(-1) == i  and basta :)

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer




---- On Mon, 06 Dec 2010 15:07:34 -0800 Igor Stasenko  wrote ----

>On 6 December 2010 23:52, jaayer  wrote:
>>
>>
>>
>>
>> ---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer  wrote ----
>>
>>>Is anyone else bother[ed] by this inconsistency?
>>
>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary and updates SmallDictionary's implementations of those messages to return the same value - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and #remove:ifAbsent: returning the key of the removed association. The second package adds #testRemove and #testRemoveIfAbsent to DictionaryTest (through a trait).
>>
>>
>
>Hello, jaayer.
>
>The point about Dictionary inconsistency was raised multiple times before.
>I was among ones of those who did that couple of years ago.
>What can i say?
>While it is much better to have consistency,
>in fact it doesn't really changes much. I don't think that #remove: in
>a form you proposed will be any userful.
>I would really keep it simply #shouldNotImplement , because it is
>unclear what is a least surprising behavior of this method for
>Dictionary.
>One might argue, that its more userful to make it same as #removeKey:,
>other one could point that its should be symmetrical to #add: ,

#add: is not part of the ANSI <abstractDictionary> protocol. It is, however, part of the ANSI <extensibleCollection> protocol:
add:
addAll:
remove:
remove:ifAbsent:
removeAll:

One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.

>but hey, then #do: should be also symmetrical to #add: , isnt? And so
>it should iterate over associations , not just values. So, it is a can
>of worms, once you open it , you can never finish the endless
>discussions :)
>It is just works in a way how we like (defined). It is like an
>imaginary numbers in math where sqrt(-1) == i and basta :)

Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?

>--
>Best regards,
>Igor Stasenko AKA sig.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Igor Stasenko
On 7 December 2010 00:18, jaayer <[hidden email]> wrote:

>
>
>
>
> ---- On Mon, 06 Dec 2010 15:07:34 -0800 Igor Stasenko  wrote ----
>
>>On 6 December 2010 23:52, jaayer  wrote:
>>>
>>>
>>>
>>>
>>> ---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer  wrote ----
>>>
>>>>Is anyone else bother[ed] by this inconsistency?
>>>
>>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary and updates SmallDictionary's implementations of those messages to return the same value - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and #remove:ifAbsent: returning the key of the removed association. The second package adds #testRemove and #testRemoveIfAbsent to DictionaryTest (through a trait).
>>>
>>>
>>
>>Hello, jaayer.
>>
>>The point about Dictionary inconsistency was raised multiple times before.
>>I was among ones of those who did that couple of years ago.
>>What can i say?
>>While it is much better to have consistency,
>>in fact it doesn't really changes much. I don't think that #remove: in
>>a form you proposed will be any userful.
>>I would really keep it simply #shouldNotImplement , because it is
>>unclear what is a least surprising behavior of this method for
>>Dictionary.
>>One might argue, that its more userful to make it same as #removeKey:,
>>other one could point that its should be symmetrical to #add: ,
>
> #add: is not part of the ANSI <abstractDictionary> protocol. It is, however, part of the ANSI <extensibleCollection> protocol:
> add:
> addAll:
> remove:
> remove:ifAbsent:
> removeAll:
>
> One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.
>
>>but hey, then #do: should be also symmetrical to #add: , isnt? And so
>>it should iterate over associations , not just values. So, it is a can
>>of worms, once you open it , you can never finish the endless
>>discussions :)
>>It is just works in a way how we like (defined). It is like an
>>imaginary numbers in math where sqrt(-1) == i and basta :)
>
> Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?

i think that most sane developers trying to avoid using inconsistent
methods with dictionaries , which inherited from Collection protocol.
So, instead of #do:, they using #valuesDo: ,  dict values select:
instead of dict select: and so on.
Because otherwise, what is the point of introducting #valuesDo:, which
completely duplicating #do: behavior? I see nothing, except an attempt
to introduce an explicit and more appropriate protocol for Dictionary.
And then ban Collection methods, with questionable behavior (depending
on who is questioning ;) ).

>
>>--
>>Best regards,
>>Igor Stasenko AKA sig.
>>
>>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer




---- On Mon, 06 Dec 2010 15:42:01 -0800 Igor Stasenko  wrote ----

>On 7 December 2010 00:18, jaayer  wrote:
>>
>>
>>
>>
>> ---- On Mon, 06 Dec 2010 15:07:34 -0800 Igor Stasenko  wrote ----
>>
>>>On 6 December 2010 23:52, jaayer  wrote:
>>>>
>>>>
>>>>
>>>>
>>>> ---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer  wrote ----
>>>>
>>>>>Is anyone else bother[ed] by this inconsistency?
>>>>
>>>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary and updates SmallDictionary's implementations of those messages to return the same value - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and #remove:ifAbsent: returning the key of the removed association. The second package adds #testRemove and #testRemoveIfAbsent to DictionaryTest (through a trait).
>>>>
>>>>
>>>
>>>Hello, jaayer.
>>>
>>>The point about Dictionary inconsistency was raised multiple times before.
>>>I was among ones of those who did that couple of years ago.
>>>What can i say?
>>>While it is much better to have consistency,
>>>in fact it doesn't really changes much. I don't think that #remove: in
>>>a form you proposed will be any userful.
>>>I would really keep it simply #shouldNotImplement , because it is
>>>unclear what is a least surprising behavior of this method for
>>>Dictionary.
>>>One might argue, that its more userful to make it same as #removeKey:,
>>>other one could point that its should be symmetrical to #add: ,
>>
>> #add: is not part of the ANSI  protocol. It is, however, part of the ANSI  protocol:
>> add:
>> addAll:
>> remove:
>> remove:ifAbsent:
>> removeAll:
>>
>> One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.
>>
>>>but hey, then #do: should be also symmetrical to #add: , isnt? And so
>>>it should iterate over associations , not just values. So, it is a can
>>>of worms, once you open it , you can never finish the endless
>>>discussions :)
>>>It is just works in a way how we like (defined). It is like an
>>>imaginary numbers in math where sqrt(-1) == i and basta :)
>>
>> Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?
>
>i think that most sane developers trying to avoid using inconsistent
>methods with dictionaries , which inherited from Collection protocol.
>So, instead of #do:, they using #valuesDo: , dict values select:
>instead of dict select: and so on.
>Because otherwise, what is the point of introducting #valuesDo:, which
>completely duplicating #do: behavior? I see nothing, except an attempt
>to introduce an explicit and more appropriate protocol for Dictionary.
>And then ban Collection methods, with questionable behavior (depending
>on who is questioning ;) ).

I am not sure if you realize this or not, but "dict values select:" and "dict select:" do two different things. The former selects the values of "dict" into a new collection, as one would expect, while the latter actually creates a new dictionary by filtering the associations from "dict" based on the values of those associations. Another datum, assuming you were unaware of the difference, for the unintuitiveness and relative uselessness of the enumeration protocol of Dictionary. When have you ever really needed something like what Dictionary>>select: or Dictionary>>collect: provides? How often are you interested only in the values of a dictionary and not their corresponding keys? It may be ANSI, but it was poorly thought out, and it stinks.

A Dictionary is an unordered collection of associations. That means #add:, #do:, #select:, #size, #includes: and other messages belonging to the basic protocol Dictionary inherits from Collection should operate on associations and not association values. At least, I suspect that's how it would be done if it could be done anew, without any concern for existing standards or backwards compatibility.

>>
>>>--
>>>Best regards,
>>>Igor Stasenko AKA sig.
>>>
>>>
>>
>>
>>
>
>
>
>--
>Best regards,
>Igor Stasenko AKA sig.
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer
In reply to this post by jaayer




---- On Mon, 06 Dec 2010 14:52:53 -0800 jaayer  wrote ----

>
>
>
>
>---- On Sun, 05 Dec 2010 12:44:46 -0800 jaayer wrote ----
>
>>Is anyone else bother[ed] by this inconsistency?
>
>Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary
> and updates SmallDictionary's implementations of those messages to return the same value

Regardless of what comes of those packages I uploaded, SmallDictionary>>remove: and SmallDictionary>>remove:ifAbsent: returning two different values is clearly a bug. Looking at it again, I was wrong about SmallDictionary>>remove:ifAbsent: returning the key; it does return the removed association. Which means at a minimum, SmallDictionary>>remove: only needs to have a ^ inserted at its beginning to fix the discrepancy.

> - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and
> #remove:ifAbsent: returning the key of the removed association.
>The second package adds #testRemove and
> #testRemoveIfAbsent to DictionaryTest (through a trait).
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Stéphane Ducasse
In reply to this post by jaayer
>>
>> Hello, jaayer.
>>
>> The point about Dictionary inconsistency was raised multiple times before.
>> I was among ones of those who did that couple of years ago.
>> What can i say?
>> While it is much better to have consistency,
>> in fact it doesn't really changes much. I don't think that #remove: in
>> a form you proposed will be any userful.
>> I would really keep it simply #shouldNotImplement , because it is
>> unclear what is a least surprising behavior of this method for
>> Dictionary.

Igor why?

why remove: does not take the same argument than add: and does what it should?

>> One might argue, that its more userful to make it same as #removeKey:,
>> other one could point that its should be symmetrical to #add: ,
>
> #add: is not part of the ANSI <abstractDictionary> protocol. It is, however, part of the ANSI <extensibleCollection> protocol:
> add:
> addAll:
> remove:
> remove:ifAbsent:
> removeAll:
>
> One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.
>
>> but hey, then #do: should be also symmetrical to #add: , isnt? And so
>> it should iterate over associations , not just values. So, it is a can
>> of worms, once you open it , you can never finish the endless
>> discussions :)
>> It is just works in a way how we like (defined). It is like an
>> imaginary numbers in math where sqrt(-1) == i and basta :)
>
> Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?

I hope not.



Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Stéphane Ducasse
In reply to this post by jaayer
did you create an issue?
and where did you publish the code?

>>> Is anyone else bother[ed] by this inconsistency?
>>
>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary
>> and updates SmallDictionary's implementations of those messages to return the same value
>
> Regardless of what comes of those packages I uploaded, SmallDictionary>>remove: and SmallDictionary>>remove:ifAbsent: returning two different values is clearly a bug. Looking at it again, I was wrong about SmallDictionary>>remove:ifAbsent: returning the key; it does return the removed association. Which means at a minimum, SmallDictionary>>remove: only needs to have a ^ inserted at its beginning to fix the discrepancy.
>
>> - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and
>> #remove:ifAbsent: returning the key of the removed association.
>> The second package adds #testRemove and
>> #testRemoveIfAbsent to DictionaryTest (through a trait).
>>
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Igor Stasenko
In reply to this post by Stéphane Ducasse
On 7 December 2010 12:49, Stéphane Ducasse <[hidden email]> wrote:

>>>
>>> Hello, jaayer.
>>>
>>> The point about Dictionary inconsistency was raised multiple times before.
>>> I was among ones of those who did that couple of years ago.
>>> What can i say?
>>> While it is much better to have consistency,
>>> in fact it doesn't really changes much. I don't think that #remove: in
>>> a form you proposed will be any userful.
>>> I would really keep it simply #shouldNotImplement , because it is
>>> unclear what is a least surprising behavior of this method for
>>> Dictionary.
>
> Igor why?
>
> why remove: does not take the same argument than add: and does what it should?
>

because with collection you can do:

collection copy do: [:xx  | collection remove: xx ].
or
collection removeAll: (collection select: [:each | each isOdd ] )

but not with dictionary.
So i don't see much reason fixing #remove: because we never going to
fix #do: anyways, which makes
all beautiful manipulations with collections useless for dictionary.


>>> One might argue, that its more userful to make it same as #removeKey:,
>>> other one could point that its should be symmetrical to #add: ,
>>
>> #add: is not part of the ANSI <abstractDictionary> protocol. It is, however, part of the ANSI <extensibleCollection> protocol:
>> add:
>> addAll:
>> remove:
>> remove:ifAbsent:
>> removeAll:
>>
>> One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.
>>
>>> but hey, then #do: should be also symmetrical to #add: , isnt? And so
>>> it should iterate over associations , not just values. So, it is a can
>>> of worms, once you open it , you can never finish the endless
>>> discussions :)
>>> It is just works in a way how we like (defined). It is like an
>>> imaginary numbers in math where sqrt(-1) == i and basta :)
>>
>> Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?
>
> I hope not.
>
>
>
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Nicolas Cellier
I agree with Igor, best implementation of remove: is

    self error: 'Dictionary cannot #remove:, please use #removeKey:'

Dictionary have two faces:
- a bag of values indexed thru a set of keys
- a set of associations (at least in st80 when association = was only
testing the key)

The second form is historical and IMO kind of private implementation details.
Moreover, now that Association = is also based on values, the second
form is not even more true.

The strange thing is to define #add: in Dictionary.
Normally we cannot add a value without a key index.
Thus the right protocol for dictionary is #at:put:

IMO, #add: intention was private, as Association should have been.
But for conveniency we decided to let this #add: protocol survive.

For remove:, you have two options:
- provide any Object (Dictionary is a Bag of values)
Then,  remove is
  self associationsDo: [:e | e value = anObject ifTrue: [self
removeKey: e key. ^anObject]].
  ^absentBlock value.
But then, you don't have symmetry with add: and remove:, so is it of any use ?

- provide an association...
But, then, what do you expect:
   Dictionary new add: #a -> 1; remove: #a -> 2

Nicolas


2010/12/7 Igor Stasenko <[hidden email]>:

> On 7 December 2010 12:49, Stéphane Ducasse <[hidden email]> wrote:
>>>>
>>>> Hello, jaayer.
>>>>
>>>> The point about Dictionary inconsistency was raised multiple times before.
>>>> I was among ones of those who did that couple of years ago.
>>>> What can i say?
>>>> While it is much better to have consistency,
>>>> in fact it doesn't really changes much. I don't think that #remove: in
>>>> a form you proposed will be any userful.
>>>> I would really keep it simply #shouldNotImplement , because it is
>>>> unclear what is a least surprising behavior of this method for
>>>> Dictionary.
>>
>> Igor why?
>>
>> why remove: does not take the same argument than add: and does what it should?
>>
>
> because with collection you can do:
>
> collection copy do: [:xx  | collection remove: xx ].
> or
> collection removeAll: (collection select: [:each | each isOdd ] )
>
> but not with dictionary.
> So i don't see much reason fixing #remove: because we never going to
> fix #do: anyways, which makes
> all beautiful manipulations with collections useless for dictionary.
>
>
>>>> One might argue, that its more userful to make it same as #removeKey:,
>>>> other one could point that its should be symmetrical to #add: ,
>>>
>>> #add: is not part of the ANSI <abstractDictionary> protocol. It is, however, part of the ANSI <extensibleCollection> protocol:
>>> add:
>>> addAll:
>>> remove:
>>> remove:ifAbsent:
>>> removeAll:
>>>
>>> One could make the argument that if Dictionary elects to implement part of it, it might as well implement the rest too.
>>>
>>>> but hey, then #do: should be also symmetrical to #add: , isnt? And so
>>>> it should iterate over associations , not just values. So, it is a can
>>>> of worms, once you open it , you can never finish the endless
>>>> discussions :)
>>>> It is just works in a way how we like (defined). It is like an
>>>> imaginary numbers in math where sqrt(-1) == i and basta :)
>>>
>>> Right... I wasn't planning on going there, but are we basically stuck with #do:, #select: #collect:, #includes: and other such messages operating on the Dictionary's values rather than its associations, forever?
>>
>> I hope not.
>>
>>
>>
>>
>
>
>
> --
> Best regards,
> Igor Stasenko AKA sig.
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

jaayer
In reply to this post by Stéphane Ducasse




---- On Tue, 07 Dec 2010 03:51:00 -0800 Stéphane Ducasse  wrote ----

>did you create an issue?
>and where did you publish the code?

I uploaded them to the PharoInbox, but as I said, only one minor change in SmallDictionary>>remove:  (adding a carrot "^" at the beginning) will fix the discrepancy between the two. But if the consensus is that Dictionary>>remove: and  Dictionary>>remove:ifAbsent: should not be implemented, maybe the same should be true of SmallDictionary as well.

>>>> Is anyone else bother[ed] by this inconsistency?
>>>
>>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary
>>> and updates SmallDictionary's implementations of those messages to return the same value
>>
>> Regardless of what comes of those packages I uploaded, SmallDictionary>>remove: and SmallDictionary>>remove:ifAbsent: returning two different values is clearly a bug. Looking at it again, I was wrong about SmallDictionary>>remove:ifAbsent: returning the key; it does return the removed association. Which means at a minimum, SmallDictionary>>remove: only needs to have a ^ inserted at its beginning to fix the discrepancy.
>>
>>> - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and
>>> #remove:ifAbsent: returning the key of the removed association.
>>> The second package adds #testRemove and
>>> #testRemoveIfAbsent to DictionaryTest (through a trait).
>>>
>>>
>>>
>>
>>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary responds to #add:, #addAll: but shouldNotImplement #remove: and #remove:ifAbsent

Stéphane Ducasse
> did you create an issue?
>> and where did you publish the code?
>
> I uploaded them to the PharoInbox, but as I said, only one minor change in SmallDictionary>>remove:  (adding a carrot "^" at the beginning) will fix the discrepancy between the two. But if the consensus is that Dictionary>>remove: and  Dictionary>>remove:ifAbsent: should not be implemented, maybe the same should be true of SmallDictionary as well.

probably.


>>>>> Is anyone else bother[ed] by this inconsistency?
>>>>
>>>> Apparently not. Well, I uploaded two packages to the PharoInbox. One adds #remove: and #remove:ifAbsent: to Dictionary
>>>> and updates SmallDictionary's implementations of those messages to return the same value
>>>
>>> Regardless of what comes of those packages I uploaded, SmallDictionary>>remove: and SmallDictionary>>remove:ifAbsent: returning two different values is clearly a bug. Looking at it again, I was wrong about SmallDictionary>>remove:ifAbsent: returning the key; it does return the removed association. Which means at a minimum, SmallDictionary>>remove: only needs to have a ^ inserted at its beginning to fix the discrepancy.
>>>
>>>> - the association removed - rather than their current behavior of #remove: returning self (no explicit return value) and
>>>> #remove:ifAbsent: returning the key of the removed association.
>>>> The second package adds #testRemove and
>>>> #testRemoveIfAbsent to DictionaryTest (through a trait).
>>>>
>>>>
>>>>
>>>
>>>
>>
>>
>>
>
>