Try this script in Pharo:
dictionary := WeakIdentityKeyDictionary new.
key := Object new.
dictionary at: key put: 'hello'.
dictionary size. " --> 1 "
key := nil.
2 timesRepeat: [Smalltalk garbageCollect].
By now the dictionary should be empty. However:
dictionary keys isEmpty. " --> true"
dictionary values isEmpty. " --> true "
as expected, but
dictionary isEmpty. " --> false ??"
dictionary size. " --> 1 !! "
It seems to be like this by design. If you read the comments of the WeakKeyDictionary
class (WeakIdentityKeyDictionary
's superclass):
I am a dictionary holding only weakly on my keys. This is a bit dangerous since at any time my keys can go away. Clients are responsible to register my instances by WeakArray such that the appropriate actions can be taken upon loss of any keys. As key may disappear at any time, my reported size may be greater than the number of keys encountered in iterations.
(emphasis mine)
The dictionary's internal array still has the association nil --> 'hello'
, and that's why the dictionary's size
is 1, but WeakIdentityKeyDictionary
's associationsDo:
check for nil
key's and avoid evaluating them (see the last line):
associationsDo: aBlock
"Evaluate aBlock for each of the receiver's elements (key/value
associations)."
super associationsDo: [:association | | key |
"Hold onto the key so it won't be collected while the block is evaluated."
key := association key.
key ifNotNil:[aBlock value: association]].
Dictionary#associations
is based on associationsDo:
, so that's why dictionary associations
is also empty.