11.6: Some Hints for Using Collections
- Page ID
- 39638
A common mistake with add: The following error is one of the most frequent Smalltalk mistakes.
| collection | 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 | 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 | 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.
| range | 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 | 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 = but not 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 bitXor:
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:
Book >> = aBook self class = aBook class ifFalse: [ ^ false ]. ^ title = aBook title and: [ authors = aBook authors ] Book >> hash ^ title hash bitXor: 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!