6.34 Maps
A map associates a value with each of a set of keys. Immutable maps can be constructed using the syntax {key_expr: val_expr, ...}, which creates a map from the values of the key_exprs to the corresponding values of the val_exprs. Note that using , in place of : creates a set with separate values, instead of a key–value mapping. More precisely, a use of curly braces with no preceding expression is parsed as an implicit use of the #%braces form.
A map is indexable using […] after a map expression with an expression for the key within […]. Mutable maps can be updated with a combination of […] and assignment operators such as := (but use ++ to functionally update an immutable map). These uses of square brackets are implemented by #%index. A map can be used as sequence, in which case it supplies a key and its associated value (as two result values) in an unspecified order.
mp.length()
is
Map.length(mp)
is
mp.values()
is
Map.values(mp)
mp.get(k)
is
Map.get(mp, k)
mp.has_key(k)
is
Map.has_key(mp, k)
mp.copy()
is
Map.copy(mp)
mp.snapshot()
is
Map.snapshot(mp)
mp.to_sequence()
is
Map.to_sequence(mp)
is
Map.append(mp, mp2, ...)
mp.remove(k)
is
Map.remove(mp, k)
mp.set(k, v)
is
MutableMap.set(mp, k, v)
mp.delete(k)
is
MutableMap.delete(mp, k)
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
|
annotation |
ReadableMap matches both mutable and immutable maps, while MutableMap matches mutable maps (created with, for example, the MutableMap constructor).
The Map.by and MutableMap.by annotation variants match only maps that use the hash and equality procedures specified by key_comp.
Static information associated by Map, etc., makes an expression acceptable as a sequence to for in static mode.
expression | |||||||||
#%braces {key_val_or_splice, ...} | |||||||||
| |||||||||
| |||||||||
| |||||||||
expression | |||||||||
#%braces {expr_or_splice, ...} | |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
repetition | |||||||||
#%braces {key_repet_or_splice, ...} | |||||||||
| |||||||||
repetition | |||||||||
#%braces {repet_or_splice, ...} |
When ... is used among the content with two repetitions (for a map) or one repetition (for a set), the paired key and value elements (for a map) or value elements (for a set) are included in the result map or set. When & map_expr or & set_expr appears among the content, the immutable map or immutable set produced by map_expr or set_expr is included in the result map or set.
Mappings or elements are added to the result map or set left-to-right, which means that a later key_expr or elem_expr may replace one earlier in the sequence. This ordering applies to mappings or elements spliced via ... and &, too.
The #%braces form is implicitly used when {…} is used in in an expression or repetition position. See also Implicit Forms.
> {1, 2, 3}
{1, 2, 3}
> {"a": 1, "b": 2}
{"a": 1, "b": 2}
> #%braces {1, 2, 3}
{1, 2, 3}
> #%braces {"a": 1, "b": 2}
{"a": 1, "b": 2}
> {1, 2, & {3, 4}}
{1, 2, 3, 4}
> {"a": 1, "b": 2, & {"c": 3, "d": 4}}
{"a": 1, "b": 2, "c": 3, "d": 4}
expression | |||||||||
Map{key_val_or_splice, ...} | |||||||||
| |||||||||
repetition | |||||||||
Map{key_repet_or_splice, ...} | |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
| |||||||||
function | |||||||||
| |||||||||
expression | |||||||||
Map.by(key_comp){key_val_or_splice, ...} | |||||||||
| |||||||||
expression | |||||||||
| |||||||||
repetition | |||||||||
The Map.by variants create a map that uses the equality and hashing functions specified by key_comp for keys.
> m
{"x": 1, "y": 2}
> m["x"]
1
> Map(["x", 1], ["y", 2])
{"x": 1, "y": 2}
{"a": 4, "b": 4, "x": 1, "y": 2}
Map.by(===){"x": 1, "x": 2}
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
| ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
| ||||||
| ||||||
|
See Map and Set for more information.
The #%braces form is implicitly used when {…} is used in in a binding position. See also Implicit Forms.
> y
2
> [z, ...]
["c", "a"]
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
ReadableMap{key_expr: val_bind, ...} | ||||||
| ||||||
binding operator | ||||||
ReadableMap{key_expr: val_bind, ..., rest} | ||||||
| ||||||
binding operator | ||||||
ReadableMap([key_expr, val_bind], ...) | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
binding operator | ||||||
| ||||||
| ||||||
| ||||||
|
The Map binding forms match only immutable maps, while ReadableMap forms match both immutable and mutable maps. For ReadableMap, the & map_bind will match a snapshot (in the sense of Map.snapshot) of the rest of the map. The Map.by binding forms match only immutable maps constructed using key_comp.
> y
2
> a
1
> rst
{"b": 2, "c": 3}
> [key, ...]
["c", "b"]
> [val, ...]
[3, 2]
| Map.by(==){}: "by equal"
| Map.by(===){}: "by object identity"
"by object identity"
The Map.by reducer creates a map that uses the equality and hashing functions specified by key_comp.
expression | ||
MutableMap{key_expr: val_expr, ...} | ||
| ||
function | ||
| ||
| ||
expression | ||
MutableMap.by(key_comp){key_expr: val_expr, ...} | ||
| ||
expression | ||
Note that ... and & are not supported for constructing mutable maps, only immutable maps.
> def m = MutableMap{"x": 1, "y": 2}
> m
MutableMap{"x": 1, "y": 2}
> m["x"]
1
> m["x"] := 0
> m
MutableMap{"x": 0, "y": 2}
value |
|
binding operator |
|
value |
|
binding operator |
The ReadableMap.empty binding form matches an empty map whether it is mutable or immutable.
Corresponding to the binding forms, Map.empty and ReadableMap.empty are bound to {} with approapriate static information.
{}
> match {}
| Map.empty: "empty map"
| _: #false
"empty map"
> match {"x": 1, "y": 2}
| Map.empty: "empty map"
| _: #false
#false
> match {"x": 1, "y": 2}
| {}: "curly braces allow extra"
| _: #false
"curly braces allow extra"
> match {"x": 1, "y": 2}
| Map(): "Map binding allows extra"
| _: #false
"Map binding allows extra"
> match MutableMap{}
| Map.empty: "empty immutable map"
| _: #false
#false
> match MutableMap{}
| ReadableMap.empty: "empty map for now"
| _: #false
"empty map for now"
function |
fun Map.length(mp :: ReadableMap) :: Int |
> Map.length({"a": 1, "b": 2})
2
> Map.length({})
0
> {"a": 1, "b": 2}.length()
2
> {}.length()
0
> {1: "a", 2: "b"}.append({1: "c"}, {1: "d"})
{1: "d", 2: "b"}
{1: "d", 2: "b"}
> Map.keys({"a": 1, "b": 2}, #true)
["a", "b"]
function |
fun Map.values(mp :: ReadableMap) :: List |
> Map.values({"a": 1, "b": 2})
[2, 1]
function | |||||
|
> Map.get({"a": 1, "b": 2}, "a")
1
> {"a": 1, "b": 2}["a"]
1
> Map.get({"a": 1, "b": 2}, "c", #inf)
#inf
no value
> Map.remove({"a": 1, "b": 2}, "a")
{"b": 2}
> Map.remove({"a": 1, "b": 2}, "c")
{"a": 1, "b": 2}
function | |||
> def m = MutableMap{"a": 1, "b": 2}
> m.set("a", 3)
> m
MutableMap{"a": 3, "b": 2}
> m["a"] := 4
> m
MutableMap{"a": 4, "b": 2}
function |
fun MutableMap.delete(mp :: MutableMap, key :: Any) :: Void |
> def m = MutableMap{"a": 1, "b": 2}
> m.delete("c")
> m
MutableMap{"a": 1, "b": 2}
> m.delete("a")
> m
MutableMap{"b": 2}
function |
fun Map.has_key(mp :: ReadableMap, key :: Any) :: Boolean |
> Map.has_key({"a": 1, "b": 2}, "a")
#true
> Map.has_key({"a": 1, "b": 2}, "c")
#false
function |
fun Map.copy(mp :: ReadableMap) :: MutableMap |
function |
fun Map.snapshot(mp :: ReadableMap) :: Map |
function |