## 9.4 Weak Dictionaries

The module `WeakDictionary` contains procedures operating on weak dictionaries. A weak dictionary is much like an ordinary dictionary and supports the same API. The main difference is that an entry is kept only as long as its item (i. e. the value recorded under the key) has not become garbage. If the item is only reachable through one or more weak dictionaries, the corresponding entries will automatically be dropped from all weak dictionaries at the next garbage collection.

Finalization Stream

Each weak dictionary is associated with a finalization stream. When an item `X` (indexed under `Key`) becomes garbage, the entry is automatically removed from the weak dictionary at the next garbage collection and the pair `Key#X` is sent on to the finalization stream (as if the weak dictionary were associated with a port and the pair was sent to it using `Port.send`). This means that the item, which was garbage, becomes again non-garbage when it is sent to the finalization stream. If subsequently, this last remaining reference disappears, then the item really becomes garbage since it won't be referenced even through a weak dictionary.

The finalization stream is created at the same time as the weak dictionary; both are output arguments of `NewWeakDictionary`. If you are not interested in the finalization stream, you can explicitly close it using `WeakDictionary.close`.

Module `WeakDictionary` can also be accessed as `Dictionary.weak`.

`IsWeakDictionary`

  > `{WeakDictionary.is` `+X``` `?B``}`

  tests whether `X` is a weak dictionary.

`NewWeakDictionary`

  > `{WeakDictionary.new` `?L``` `?Weak``}`

  has the same arguments as `Port.new`. Returns a new empty weak dictionary associated with a new finalization stream `L`.

`close`

  > `{WeakDictionary.close` `+Weak``}`

  drops the finalization stream (if any). After this, any entry that becomes garbage is simply dropped instead of being sent to the finalization stream.

`put`

  > `{WeakDictionary.put` `+Weak``` `+LI``` `X``}`

  sets the item in `Weak` under key `LI` to `X`.

`get`

  > `{WeakDictionary.get` `+Weak``` `+LI``` `X``}`

  returns the item `X` of `Weak` under key `LI`.

`condGet`

  > `{WeakDictionary.condGet` `+Weak``` `+LI``` `X``` `Y``}`

  returns the item `Y` of `Weak` under key `LI`, if `LI` is a valid key of `Weak`. Otherwise, returns `X`.

`keys`

  > `{WeakDictionary.keys` `+Weak``` `?LIs``}`

  returns a list of all currently valid keys of `Weak`.

`entries`

  > `{WeakDictionary.entries` `+Weak``` `?Ts``}`

  returns the list of current entries of `Weak`. An entry is a pair `LI``#``X`, where `LI` is a valid key of `Weak` and `X` the corresponding item.

`items`

  > `{WeakDictionary.items` `+Weak``` `?Xs``}`

  returns the list of all items currently in `Weak`.

`isEmpty`

  > `{WeakDictionary.isEmpty` `+Weak``` `?B``}`

  tests whether `Weak` currently contains an entry.

`remove`

  > `{WeakDictionary.remove` `+Weak``` `+LI``}`

  removes the item under key `LI` from `Weak` if `LI` is a valid key. Otherwise, does nothing.

`removeAll`

  > `{WeakDictionary.removeAll` `+Weak``}`

  removes all entries currently in `Weak`.

`member`

  > `{WeakDictionary.member` `+Weak``` `+LI``` `?B``}`

  tests whether `LI` is a valid key of `Weak`.

`toRecord`

  > `{WeakDictionary.toRecord` `+L``` `+Weak``` `?R``}`

  returns a record `R` with label `L` whose features and their fields correspond to the keys and their entries of `Weak`.