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 |
"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 |
"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 |
Free forum by Nabble | Edit this page |