9.6: Some Hints for Using Collections
- Page ID
- 36383
A common mistake with add: The following error is one of the most frequent Smalltalk mistakes.
collection := OrderedCollection new add: 1; add: 2. collection → 2
Here the variable collection does not hold the newly created collection but rather the last number added. This is because the method add:
returns the element added and not the receiver.
The following code yields the expected result:
collection := OrderedCollection new. collection add: 1; add: 2. collection → an OrderedCollection(1 2)
You can also use the message yourself
to return the receiver of a cascade of messages:
collection := OrderedCollection new add: 1; add: 2; yourself → an OrderedCollection(1 2)
Removing an element of the collection you are iterating on. Another mistake you may make is to remove an element from a collection you are currently iterating over. remove:
range := (2 to: 20) asOrderedCollection. range do: [:aNumber | aNumber isPrime ifFalse: [ range remove: aNumber ] ]. range → an OrderedCollection(2 3 5 7 9 11 13 15 17 19)
This result is clearly incorrect since 9 and 15 should have been filtered out! The solution is to copy the collection before going over it.
range := (2 to: 20) asOrderedCollection. range copy do: [:aNumber | aNumber isPrime ifFalse: [ range remove: aNumber ] ]. range → an OrderedCollection(2 3 5 7 11 13 17 19)
Redefining both = and hash. A difficult error to spot is when you redefine = but not hash
. The symptoms are that you will lose elements that you put in sets or other strange behaviour. One solution proposed by Kent Beck is to use xor:
to redefine hash
. Suppose that we want two books to be considered equal if their titles and authors are the same. Then we would redefine not only = but also hash
as follows:
Code \(\PageIndex{1}\) (Squeak): Redefining = and hash.
Book»= aBook self class = aBook class ifFalse: [↑ false]. ↑ title = aBook title and: [ authors = aBook authors] Book»hash ↑ title hash xor: authors hash
Another nasty problem arises if you use a mutable object, i.e., an object that can change its hash value over time, as an element of a Set
or as a key to a Dictionary
. Don’t do this unless you love debugging!