BUG: Dictionary<<copy does not copy associations, and causes unexpected behavior.

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

BUG: Dictionary<<copy does not copy associations, and causes unexpected behavior.

Christopher J. Demers
I encountered what appeared to be a very strange situation.  I was working
on a postCopy method that needed to make a copy of all values in a
Dictionary that my object contained, but found that it was not working as
expected.  I examined every part of the method and noticed a very scary copy
problem.  The code snippet bellow reproduces the quirk on Dolphin 5.1.4.
The same code works as expected in Squeak.

The problem is that Dictionary<<copy does not make a copy of the
associations.  If one adds a new value to a copied Dictionary then all
appears to be fine.  However if one changes a value at an existing key then
the original Dictionary is changed as well.  That is bad.  The fix I propose
would be to add a postCopy method to Dictionary to ensure that all contained
associations are also copied.

=====================
dictA := Dictionary new.
dictA at: 'key' put: 'value'.
originalAValue := dictA at: 'key'.
dictB := dictA copy.
dictB at: 'key' put: (dictA at: 'key') copy.
(dictA at: 'key') == (dictB at: 'key'). "Should be false, but is true."
originalAValue == (dictA at: 'key'). "Should be true, but is false."
====================

A unit test can be found
http://www.mitchellscientific.com/smalltalk/temp/MitSciUnitTestsForOA.pac .

Chris


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary<<copy does not copy associations, and causes unexpected behavior.

Blair McGlashan
"Christopher J. Demers" <[hidden email]> wrote in
message news:[hidden email]...
> I encountered what appeared to be a very strange situation.  I was working
> on a postCopy method that needed to make a copy of all values in a
> Dictionary that my object contained, but found that it was not working as
> expected.  I examined every part of the method and noticed a very scary
copy
> problem.  The code snippet bellow reproduces the quirk on Dolphin 5.1.4.
> The same code works as expected in Squeak.
>
> The problem is that Dictionary<<copy does not make a copy of the
> associations.  If one adds a new value to a copied Dictionary then all
> appears to be fine.  However if one changes a value at an existing key
then
> the original Dictionary is changed as well.  That is bad.  The fix I
propose
> would be to add a postCopy method to Dictionary to ensure that all
contained
> associations are also copied.

This is not really a bug. Squeak's behaviour is "non-standard" - if you try
your example in VW you will see that it behaves in the same way as Dolphin.

The only real reason to use a Dictionary (instead of a LookupTable) is to
take advantage of the fact that they are "a Set of Associations", and those
Associations are maintained for the life of the dictionary, and can be
captured and updated externally with any changes being reflected in the
dictionary, i.e. the use of Associations in a Dictionary is not just an
implementation detail, but an important public property of the data
structure. An example of such usage is for variable bindings where the
variable binding itself should remain constant (and unique) but its value
can change. In practice, though, the occassions where this is useful are
rare, and you will find very few instances of Dictonary itself in a standard
Dolphin image. #copy on collections is (in general) defined as a copy of the
collection itself, but not the elements. Dictionary has a rather ambiguous
notion of what constitute its elements, but in many respects, including for
copying, the elements are considered to be the associations, and so these
are not copied. If this is not the type of copy that you need, then you can
define your own by deepening a shallow copy appropriately - VW's
#copyWithCopiedValues is one such. The other alternative is to use a
LookupTable, since these do implement the copying behaviour you desire. We
would recommend the use of LookupTable anyway as the default choice for most
mapping tasks, since they are more efficient than dictionaries.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Dictionary<<copy does not copy associations, and causes unexpected behavior.

Christopher J. Demers
"Blair McGlashan" <[hidden email]> wrote in message
news:[hidden email]...
> "Christopher J. Demers" <[hidden email]> wrote in
> message news:[hidden email]...
> > I encountered what appeared to be a very strange situation.  I was
working
> > on a postCopy method that needed to make a copy of all values in a
> > Dictionary that my object contained, but found that it was not working
as
...
> This is not really a bug. Squeak's behaviour is "non-standard" - if you
try
> your example in VW you will see that it behaves in the same way as
Dolphin.
...

Thanks for looking into this, I figured there was a chance you might say
that. ;)  I do try to use LookupTables in new code, but my Dictionaries are
in old code and are saved in ReStore, and I am not sure if ReStore supports
handling of LookupTables (I should look into that).

The reason I got into my little mess was that I used
SelectorEnvironment<<postCopy as an example for my postCopy method.  The
intent of that method seems to be to make a copy of the dictionary, and
copies of the values.  However it would seem to have the same issue I ran
into.  The original dictionary would get the same copy of the value as the
copy.
This may just happen not to be a real problem in this case, but it might be
worth double checking the code.

Chris