An IdentityDictionary is an associative collection mapping keys to values. Keys and values can be arbitrary objects, but for keys, often a Symbol is used.
Often, the subclass Event is used as an IdentityDictionary, because there is a syntactical shortcut:
The contents of a Dictionary are unordered. You must not depend on the order of items in a Dictionary.
IdentityDictionary is often used to assign names to instances of a particular class. For example, the proxy classes ( Pdef, Pdefn, Tdef, Ndef ), and NodeWatcher all have class variables named all implemented as IdentityDictionaries.
IdentityDictionary has three levels of content: the dictionary itself, a proto
, and a parent
. proto
and parent
exist primarily for IdentityDictionary's subclass Event, which uses the parent
to store action functions that will be used when an event is played. Users may put additional default values into the proto
.
Looking up a key within a dictionary first checks the dictionary itself. If the key is not found at this level, it looks in the proto
, and if still not found, it looks in the parent.
These extra levels are meant for common, default values that should be the same across many dictionary instances.
proto
and parent
values are not shown when posting the dictionary.do
-- they will not be processed in the iteration, and as with copy
, they are identical references.The -parent and -proto instance variables allow additional IdentityDictionary's to provide default values. The precedence order for determining the value of a key is the IdentityDictionary, its prototype, its parent.
When the instance variable -know is True, the IdentityDictionary responds to unknown messages by looking up the selector and evaluating the result with the dictionary as an argument. For example:
In the subclass Event, "know" is true by default, so that it can be instantly used for prototype objects. The first argument passed to the functions is in such cases always the dictionary/event itself (here denoted by "self").
If set to true, the dictionary interprets method calls as look ups. This allows you to implement object prototypes (see above).
Sets key to newValue, returns the previous value of key.
Returns true if the key exists in the dictionary
Returns the key for a given value (it'll return the first it finds, so this may be ambiguous).
If such reverse lookup is needed a lot, for efficiency you may consider using a TwoWayIdentityDictionary instead.
The two instance variables proto and parent may hold dictionaries which are used to look up all those keys that have no value in the current dictionary. First, proto is looked up, then parent. In other words: proto overrides parent. This allows you to construct systems with complex defaults or multiple inheritance.
Inserts a dictionary into the chain of parents of the receiver (rather than replacing the parent).
newParent |
The dictionary that is added to the parent chain |
insertionDepth |
Level at which the new parent is inserted. Zero (default) means directly above, Inf means at the top of the parent chain. |
reverseInsertionDepth |
If the new parent dictionary has parents itself, this parameter specifies where the original parents are placed in the new parent chain. Zero means directly above, Inf (default) means at the top of the chain. Compare a.insertParent(b, 0) and a.insertParent(b, 1) Compare a.insertParent(b, 0, inf) and a.insertParent(b, 0, 0) |
Use a dictionary to represent timing information.
For optimizing the garbage collector load, objects can be frozen and become immutable. This method creates a new dictionary with the frozen instance as a parent so that all contents can be overwritten without losing this optimization.