# map¶

`meth (Key: any):in(Map: map): any | nil`

Returns `Key` if it is in `Map`, otherwise return `nil`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
"A" in M :> "A"
"D" in M :> nil
```
`type map < sequence`

A map of key-value pairs. Keys can be of any type supporting hashing and comparison. By default, iterating over a map generates the key-value pairs in the order they were inserted, however this ordering can be changed.

`meth map(Key₁ is Value₁, ...): map`

Returns a new map with the specified keys and values.

```map(A is 1, B is 2, C is 3)
:> {"A" is 1, "B" is 2, "C" is 3}
```
`meth map(Sequence: sequence, ...): map`

Returns a map of all the key and value pairs produced by `Sequence`.

```map("cake") :> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
```
`meth map(): map`

Returns a new map.

```map() :> {}
```
`fun map::join(Map₁, : map, ..., Fn: function): map`

Returns a new map containing the union of the keys of `Mapᵢ`, and with values `Fn(V₁, ..., Vₙ)` where each `Vᵢ` comes from `Mapᵢ` (or `nil`).

```let A := map(swap("apple"))
:> {"a" is 1, "p" is 3, "l" is 4, "e" is 5}
let B := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
let C := map(swap("pear"))
:> {"p" is 1, "e" is 2, "a" is 3, "r" is 4}
map::join(A, B, C, tuple)
:> {"a" is (1, 6, 3), "p" is (3, nil, 1), "l" is (4, nil, nil), "e" is (5, nil, 2), "b" is (nil, 1, nil), "n" is (nil, 5, nil), "r" is (nil, nil, 4)}
```
`fun map::join2(Map₁, : map, ..., Fn: function): map`

Returns a new map containing the union of the keys of `Mapᵢ`, and with values `Fn(K, V₁, ..., Vₙ)` where each `Vᵢ` comes from `Mapᵢ` (or `nil`).

```let A := map(swap("apple"))
:> {"a" is 1, "p" is 3, "l" is 4, "e" is 5}
let B := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
let C := map(swap("pear"))
:> {"p" is 1, "e" is 2, "a" is 3, "r" is 4}
map::join2(A, B, C, tuple)
:> {"a" is (a, 1, 6, 3), "p" is (p, 3, nil, 1), "l" is (l, 4, nil, nil), "e" is (e, 5, nil, 2), "b" is (b, nil, 1, nil), "n" is (n, nil, 5, nil), "r" is (r, nil, nil, 4)}
```
`meth (Map: map) :: (Key: string): map::node`

Same as `Map[Key]`. This method allows maps to be used as modules.

```let M := copy({"A" is 1, "B" is 2, "C" is 3}, :const)
M::A
:> error("MethodError", "no method found for ::(visitor, string)")
M::D
:> error("MethodError", "no method found for ::(visitor, string)")
```
`meth (Map₁: map) * (Map₂: map): map`

Returns a new map containing the entries of `Map₁` which are also in `Map₂`. The values are chosen from `Map₂`.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A * B :> {"b" is 1, "a" is 4}
```
`meth (Map₁: map) + (Map₂: map): map`

Returns a new map combining the entries of `Map₁` and `Map₂`. If the same key is in both `Map₁` and `Map₂` then the corresponding value from `Map₂` is chosen.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A + B
:> {"b" is 1, "a" is 4, "n" is 5, "r" is 2, "e" is 3, "d" is 5}
```
`meth (Map₁: map) / (Map₂: map): map`

Returns a new map containing the entries of `Map₁` which are not in `Map₂`.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A / B :> {"n" is 5}
```
`meth (Map₁: map) /(Map₂: map): map`

Returns a new map containing the entries of `Map₁` which are also in `Map₂`. The values are chosen from `Map₂`.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A /\ B :> {"b" is 1, "a" is 4}
```
`meth (Map₁: map) <=> (Map₂: map): map`

Returns a tuple of `(Map₁ / Map₂, Map₁ * Map₂, Map₂ / Map₁)`.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A <=> B
:> ({n is 5}, {b is 1, a is 6}, {r is 2, e is 3, d is 5})
```
`meth (Map₁: map) >< (Map₂: map): map`

Returns a new map containing the entries of `Map₁` and `Map₂` that are not in both.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A >< B :> {"n" is 5, "r" is 2, "e" is 3, "d" is 5}
```
`meth (Map: map)[Key: any]: any | nil`

Returns the value corresponding to `Key` in `Map`, or `nil` if `Key` is not in `Map`.

```let M := copy({"A" is 1, "B" is 2, "C" is 3}, :const)
M["A"]
:> error("MethodError", "no method found for [](visitor, string)")
M["D"]
:> error("MethodError", "no method found for [](visitor, string)")
```
`meth (Map₁: map) / (Map₂: map): map`

Returns a new map combining the entries of `Map₁` and `Map₂`. If the same key is in both `Map₁` and `Map₂` then the corresponding value from `Map₂` is chosen.

```let A := map(swap("banana"))
:> {"b" is 1, "a" is 6, "n" is 5}
:> {"b" is 1, "r" is 2, "e" is 3, "a" is 4, "d" is 5}
A \/ B
:> {"b" is 1, "a" is 4, "n" is 5, "r" is 2, "e" is 3, "d" is 5}
```
`meth (Map: map):count: integer`

Returns the number of entries in `Map`.

```{"A" is 1, "B" is 2, "C" is 3}:count :> 3
```
`meth (Map: map):first`

Returns the first value in `Map` or `nil` if `Map` is empty.

`meth (Map: map):from(Key: any): sequence | nil`

Returns the subset of `Map` after `Key` as a sequence.

```let M := {"A" is 1, "B" is 2, "C" is 3, "D" is 4, "E" is 5}
map(M:from("C")) :> {"C" is 3, "D" is 4, "E" is 5}
map(M:from("F")) :> {}
```
`meth (Map: map):last`

Returns the last value in `Map` or `nil` if `Map` is empty.

`meth (Map: map):order: map::order`

Returns the current ordering of `Map`.

`meth (Map: map):precount: integer`

Returns the number of entries in `Map`.

```{"A" is 1, "B" is 2, "C" is 3}:count :> 3
```
`meth (List: map):random: any`

Returns a random (assignable) node from `Map`.

```let M := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M:random :> "a"
M:random :> "e"
```
`meth (Map: map):size: integer`

Returns the number of entries in `Map`.

```{"A" is 1, "B" is 2, "C" is 3}:size :> 3
```
`meth (Buffer: string::buffer):append(Map: map)`

Appends a representation of `Map` to `Buffer`.

`meth (Buffer: string::buffer):append(Map: map, Sep: string, Conn: string)`

Appends the entries of `Map` to `Buffer` with `Conn` between keys and values and `Sep` between entries.

`type map::mutable < map`

TBD

`meth (Map: map::mutable) :: (Key: string): map::node`

Same as `Map[Key]`. This method allows maps to be used as modules.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M::A :> 1
M::D :> nil
M::A := 10 :> 10
M::D := 20 :> 20
M :> {"A" is 10, "B" is 2, "C" is 3, "D" is 20}
```
`meth (Map: map::mutable)[Key: any]: map::node`

Returns the node corresponding to `Key` in `Map`. If `Key` is not in `Map` then a new floating node is returned with value `nil`. This node will insert `Key` into `Map` if assigned.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M["A"] :> 1
M["D"] :> nil
M["A"] := 10 :> 10
M["D"] := 20 :> 20
M :> {"A" is 10, "B" is 2, "C" is 3, "D" is 20}
```
`meth (Map: map::mutable)[Key: any, Fn: function]: map::node`

Returns the node corresponding to `Key` in `Map`. If `Key` is not in `Map` then `Fn(Key)` is called and the result inserted into `Map`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M["A", fun(Key) Key:code] :> 1
M["D", fun(Key) Key:code] :> 68
M :> {"A" is 1, "B" is 2, "C" is 3, "D" is 68}
```
`meth (Map: map::mutable):delete(Key: any): any | nil`

Removes `Key` from `Map` and returns the corresponding value if any, otherwise `nil`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M:delete("A") :> 1
M:delete("D") :> nil
M :> {"B" is 2, "C" is 3}
```
`meth (Map: map::mutable):empty: map`

Deletes all keys and values from `Map` and returns it.

```let M := {"A" is 1, "B" is 2, "C" is 3}
:> {"A" is 1, "B" is 2, "C" is 3}
M:empty :> {}
```
`meth (Map: map::mutable):grow(Sequence: sequence, ...): map`

Adds of all the key and value pairs produced by `Sequence` to `Map` and returns `Map`.

```map("cake"):grow("banana")
:> {1 is "b", 2 is "a", 3 is "n", 4 is "a", 5 is "n", 6 is "a"}
```
`meth (Map: map::mutable):insert(Key: any, Value: any): any | nil`

Inserts `Key` into `Map` with corresponding value `Value`. Returns the previous value associated with `Key` if any, otherwise `nil`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M:insert("A", 10) :> 1
M:insert("D", 20) :> nil
M :> {"A" is 10, "B" is 2, "C" is 3, "D" is 20}
```
`meth (Map: map::mutable):missing(Key: any): some | nil`

If `Key` is present in `Map` then returns `nil`. Otherwise inserts `Key` into `Map` with value `some` and returns `some`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M:missing("A") :> nil
M:missing("D") :> some
M :> {"A" is 1, "B" is 2, "C" is 3, "D"}
```
`meth (Map: map::mutable):missing(Key: any, Fn: function): any | nil`

If `Key` is present in `Map` then returns `nil`. Otherwise inserts `Key` into `Map` with value `Fn(Key)` and returns `some`.

```let M := {"A" is 1, "B" is 2, "C" is 3}
M:missing("A", fun(Key) Key:code) :> nil
M:missing("D", fun(Key) Key:code) :> some
M :> {"A" is 1, "B" is 2, "C" is 3, "D" is 68}
```
`meth (Map: map::mutable):order(Order: map::order): map`

Sets the ordering

`meth (Map: map::mutable):pop: any | nil`

Deletes the first key-value pair from `Map` according to its iteration order. Returns the deleted value, or `nil` if `Map` is empty.

```:> Insertion order (default)
let M1 := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M1:pop :> "c"
M1 :> {2 is "a", 3 is "k", 4 is "e"}

:> LRU order
let M2 := map("cake"):order(map::order::LRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M2; M2; M2; M2
M2:pop :> "a"
M2 :> {4 is "e", 1 is "c", 3 is "k"}

:> MRU order
let M3 := map("cake"):order(map::order::MRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M3; M3; M3; M3
M3:pop :> "k"
M3 :> {1 is "c", 4 is "e", 2 is "a"}
```
`meth (Map: map::mutable):pop2: tuple[any, any] | nil`

Deletes the first key-value pair from `Map` according to its iteration order. Returns the deleted key-value pair, or `nil` if `Map` is empty.

```:> Insertion order (default)
let M1 := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M1:pop2 :> (1, c)
M1 :> {2 is "a", 3 is "k", 4 is "e"}

:> LRU order
let M2 := map("cake"):order(map::order::LRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M2; M2; M2; M2
M2:pop2 :> (2, a)
M2 :> {4 is "e", 1 is "c", 3 is "k"}

:> MRU order
let M3 := map("cake"):order(map::order::MRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M3; M3; M3; M3
M3:pop2 :> (3, k)
M3 :> {1 is "c", 4 is "e", 2 is "a"}
```
`meth (Map: map::mutable):pull: any | nil`

Deletes the last key-value pair from `Map` according to its iteration order. Returns the deleted value, or `nil` if `Map` is empty.

```:> Insertion order (default)
let M1 := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M1:pull :> "e"
M1 :> {1 is "c", 2 is "a", 3 is "k"}

:> LRU order
let M2 := map("cake"):order(map::order::LRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M2; M2; M2; M2
M2:pull :> "k"
M2 :> {2 is "a", 4 is "e", 1 is "c"}

:> MRU order
let M3 := map("cake"):order(map::order::MRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M3; M3; M3; M3
M3:pull :> "a"
M3 :> {3 is "k", 1 is "c", 4 is "e"}
```
`meth (Map: map::mutable):pull2: tuple[any, any] | nil`

Deletes the last key-value pair from `Map` according to its iteration order. Returns the deleted key-value pair, or `nil` if `Map` is empty.

```:> Insertion order (default)
let M1 := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M1:pull2 :> (4, e)
M1 :> {1 is "c", 2 is "a", 3 is "k"}

:> LRU order
let M2 := map("cake"):order(map::order::LRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M2; M2; M2; M2
M2:pull2 :> (3, k)
M2 :> {2 is "a", 4 is "e", 1 is "c"}

:> MRU order
let M3 := map("cake"):order(map::order::MRU)
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M3; M3; M3; M3
M3:pull2 :> (2, a)
M3 :> {3 is "k", 1 is "c", 4 is "e"}
```
`meth (Map: map::mutable):push(Key: any, Value: any): map`

Inserts `Key` into `Map` with corresponding value `Value`.

```let M := {"B" is 2, "C" is 3, "A" is 1}:order(map::order::Descending)
M:push("A", 10) :> {"A" is 10, "B" is 2, "C" is 3}
M:push("D", 20)
:> {"D" is 20, "A" is 10, "B" is 2, "C" is 3}
M :> {"D" is 20, "A" is 10, "B" is 2, "C" is 3}
```
`meth (Map: map::mutable):put(Key: any, Value: any): map`

Inserts `Key` into `Map` with corresponding value `Value`.

```let M := {"B" is 2, "C" is 3, "A" is 1}:order(map::order::Descending)
M:put("A", 10) :> {"B" is 2, "C" is 3, "A" is 10}
M:put("D", 20)
:> {"B" is 2, "C" is 3, "A" is 10, "D" is 20}
M :> {"B" is 2, "C" is 3, "A" is 10, "D" is 20}
```
`meth (Map: map::mutable):reverse: map`

Reverses the iteration order of `Map` in-place and returns it.

```let M := map("cake")
:> {1 is "c", 2 is "a", 3 is "k", 4 is "e"}
M:reverse :> {4 is "e", 3 is "k", 2 is "a", 1 is "c"}
```
`meth (Map: map::mutable):sort: Map`

Sorts the entries (changes the iteration order) of `Map` using `Keyᵢ < Keyⱼ` and returns `Map`.

```let M := map(swap("cake"))
:> {"c" is 1, "a" is 2, "k" is 3, "e" is 4}
M:sort :> {"a" is 2, "c" is 1, "e" is 4, "k" is 3}
```
`meth (Map: map::mutable):sort(Cmp: function): Map`

Sorts the entries (changes the iteration order) of `Map` using `Cmp(Keyᵢ, Keyⱼ)` and returns `Map`

```let M := map(swap("cake"))
:> {"c" is 1, "a" is 2, "k" is 3, "e" is 4}
M:sort(>) :> {"k" is 3, "e" is 4, "c" is 1, "a" is 2}
```
`meth (Map: map::mutable):sort2(Cmp: function): Map`

Sorts the entries (changes the iteration order) of `Map` using `Cmp(Keyᵢ, Keyⱼ, Valueᵢ, Valueⱼ)` and returns `Map`

```let M := map(swap("cake"))
:> {"c" is 1, "a" is 2, "k" is 3, "e" is 4}
M:sort(fun(K1, K2, V1, V2) V1 < V2)
:> {"e" is 4, "k" is 3, "a" is 2, "c" is 1}
```
`meth (Map: map::mutable):take(Source: map::mutable): map`

Inserts the key-value pairs from `Source` into `Map`, leaving `Source` empty.

```let A := map(swap("cat"))
:> {"c" is 1, "a" is 2, "t" is 3}
let B := map(swap("cake"))
:> {"c" is 1, "a" is 2, "k" is 3, "e" is 4}
A:take(B)
:> {"c" is 1, "a" is 2, "t" is 3, "k" is 3, "e" is 4}
A :> {"c" is 1, "a" is 2, "t" is 3, "k" is 3, "e" is 4}
B :> {}
```
`type map::node`

A node in a `map`. Dereferencing a `map::node::const` returns the corresponding value from the `map`.

`type map::node::mutable < map::node`

A node in a `map`. Dereferencing a `map::node` returns the corresponding value from the `map`. Assigning to a `map::node` updates the corresponding value in the `map`.

`type map::node::mutable`

A node in a `map`. Dereferencing a `map::node` returns the corresponding value from the `map`. Assigning to a `map::node` updates the corresponding value in the `map`.

`type map::order < enum`
• `map::order::Insert` ↔ default ordering; inserted pairs are put at end, no reordering on access.

• `map::order::Ascending` ↔ inserted pairs are kept in ascending key order, no reordering on access.

• `map::order::Descending` ↔ inserted pairs are kept in descending key order, no reordering on access.

• `map::order::MRU` ↔ inserted pairs are put at start, accessed pairs are moved to start.

• `map::order::LRU` ↔ inserted pairs are put at end, accessed pairs are moved to end.

`fun map::reduce(Sequence: sequence, Reduce: function)`

Creates a new map, `Map`, then applies `Map[Key] := Reduce(old, Value)` for each `Key`, `Value` pair generated by `Sequence`, finally returning `Map`.

```map::reduce(swap("banana"); L := [], I) L:put(I)
:> {"b" is , "a" is [2, 4, 6], "n" is [3, 5]}
```
`meth (Copy: visitor):const(Map: map): map::const`

Returns a new constant map containing copies of the keys and values of `Map` created using `Copy`.

`meth (Copy: visitor):copy(Map: map): map`

Returns a new map contains copies of the keys and values of `Map` created using `Copy`.

`meth (Copy: visitor):visit(Map: map): map`

Returns a new map contains copies of the keys and values of `Map` created using `Copy`.