Everyday data structures in Mako use one monomorphized surface — no special collection package, no iterator types, no hand-rolled hashes for common keys.
This guide covers:
[]T and nested [][]Tmap[K]V across the full key/value gridmap[K]Option[T] / map[K]Result[T,E] (incl. nested bags)Option / Resultmaps_*)Identity and low-ceremony patterns: ERGONOMICS.md.
Current syntax: GUIDE.md §4b–4c · book tour: ch03.
The language supports a large map/slice/bag surface, but codegen only
emits C helpers for map[K]V shapes that appear in the compilation unit
(AST walk). Large programs with many structs no longer pay N² unused
map[StructA]StructB / bag monomorphs.
| Principle | Practice |
|---|---|
| Use what you need | make(map[A]B) emits helpers for that pair only |
| Annotate API maps | Helps collection and call sites stay clear |
| Prefer shallow nests | Depth ≤3 nested maps; deep bag nests only where useful |
| Measure big packs | mako build --emit-c path.mko then check .c size |
This is what keeps multi-hundred-type packs (e.g. large libraries) compile-time friendly while still offering rich bag and channel map values.
fn main() {
let mut xs = [1, 2, 3]
xs = append(xs, 4)
print(len(xs)) // 4
print(xs[0]) // 1
let mid = xs[1:3] // [2, 3]
let tail = xs[2:]
let head = xs[:2]
// Pre-size when you know capacity
let mut buf = make([]int, 0, 64)
buf = append(buf, 10)
// Nested slices
let grid: [][]int = [[1, 2], [3, 4]]
print(grid[0][1]) // 2
// Bool / string / float / struct / enum elements all work
let flags: []bool = [true, false]
let names: []string = ["a", "b"]
// Option / Result elements (bag slices)
let mut maybe = make([]Option[int], 0, 4)
maybe = append(maybe, Some(1))
maybe = append(maybe, None)
match maybe[0] {
Some(v) => print(v),
None => print("none"),
}
let xs: []Option[int] = [Some(10), None]
let mut tried = make([]Result[string, string], 0, 2)
tried = append(tried, Ok("yes"))
tried = append(tried, Err("no"))
}
| Op | Notes |
|---|---|
len / cap |
length and capacity |
s[i] / s[i] = v |
bounds-checked (unless unsafe) |
append(s, v) |
may reallocate; reassign result |
s[low:high] |
sub-slice |
make([]T, len[, cap]) |
allocate ([]Option[T] / []Result[T,E] supported) |
Keys: int · string · float · bool · named struct · named enum
(including pack-qualified types after pull).
Values: the same set, plus:
| Value shape | Example |
|---|---|
| Scalar / struct / enum | map[string]int, map[int]Point |
| Set-style | map[string]bool |
| Slice | map[string][]int, map[Point][]string |
| Nested slice | map[string][][]int |
| Nested map (depth 2) | map[string]map[string]int |
| Nested map (depth 3) | map[string]map[string]map[string]int |
| Nested map + slices | map[string]map[string][]int |
| Slice of maps | []map[string]int |
| Map of slice-of-maps | map[string][]map[string]int |
| Option bag | map[string]Option[int] |
| Result bag | map[int]Result[string, string] |
| Slice of bags | map[string][]Option[int], map[int][]Result[string,string] |
| Bag of slices | map[string]Option[[]int], map[int]Result[[]int,string] |
| Tuple values | map[string](int, int), map[string](Point, int), map[K](int,int,int,int) |
| Bag of maps | map[string]Option[map[string]int], map[int]Result[map[string]int,string] |
| Channel values | map[string]chan[int], map[Point]chan[string], map[string]chan[Point] |
| Slice of channels | map[string][]chan[int], map[Point][]chan[string] |
| Optional channel | map[string]Option[chan[int]], Option[chan[int]] |
| Result channel | map[int]Result[chan[string],string] |
| Slice of optional channels | map[string][]Option[chan[int]] |
| Optional channel slice | map[string]Option[[]chan[int]] |
| Nested channel slices | map[string][][]chan[int] |
| Channel + scalar tuple | map[string](chan[int], int), map[int](int, chan[string]) |
| Channel 3-tuple | map[string](chan[int], int, int), (int, chan[T], int) |
| Nested optional | map[string]Option[Option[int]], Option[Option[chan[int]]] |
| Triple optional | map[string]Option[Option[Option[int]]] |
| Result of optional channel | map[int]Result[Option[chan[string]],string] |
| Option of Result | map[string]Option[Result[int,string]], Option[Result[chan[int],string]] |
| Result of nested optional | map[string]Result[Option[Option[int]],string] |
| Nested Result | map[string]Result[Result[int,string],string] |
| Slice of nested bags | map[string][]Option[Option[int]], []Option[Result[int,string]] |
| Optional bag slice | map[string]Option[[]Option[int]], Result[[]Result[int,string],string] |
| Bag-field tuples | map[string](Option[int], int), (Result[string,string], int), (Option[chan[int]], int) |
struct Point { x: int, y: int }
enum Color { Red, Green }
fn demo_maps() {
let mut m = make(map[string]int)
m["a"] = 1
print(m["a"]) // 1
print(m["missing"]) // 0 (zero value)
if has(m, "a") { }
let v, ok = m["a"] // comma-ok
delete(m, "a")
for k, v in range m {
print(k)
print(v)
}
// Struct / enum keys (field-wise / tag eq)
let mut by_pt = make(map[Point]int)
by_pt[Point { x: 1, y: 2 }] = 10
let mut by_e = make(map[Color][]string)
by_e[Red] = ["hot"]
// Named mailboxes: map of channels (pointer values; missing → nil)
let mut inbox = make(map[string]chan[int])
let ch = chan_open[int](4)
inbox["worker"] = ch
let _ = inbox["worker"].send(1)
}
Float keys: +0.0 and -0.0 are the same key; all NaNs share one key.
Missing key → zero value (nil channel for map[K]chan[T]). len on a nil map is 0.
maps_clone / maps_equal on channel maps are shallow (same channel handles).
fn sets_and_groups() {
// Set
let mut seen = make(map[string]bool)
seen["alice"] = true
if has(seen, "alice") {
print("known")
}
// Group by key
let mut groups = make(map[string][]int)
groups["even"] = [2, 4, 6]
groups["odd"] = [1, 3]
print(len(groups["even"])) // 3
print(groups["even"][0]) // 2
}
Build the inner map, then store it. Nested-map values are pointers;
missing outer key yields a nil map (len 0). maps_clone / maps_equal are
shallow (inner pointer identity).
fn nested_demo() {
let mut outer = make(map[string]map[string]int)
let mut row = make(map[string]int)
row["x"] = 1
row["y"] = 2
outer["a"] = row
print(outer["a"]["x"]) // 1
// Nested map whose values are slices
let mut by_user = make(map[string]map[string][]int)
let mut scores = make(map[string][]int)
scores["math"] = [90, 95]
by_user["ada"] = scores
}
Depth 3 (map[K]map[K2]map[K3]V) is not supported yet.
Store nullable or fallible data per key without sentinel ints:
fn bag_demo() {
let mut maybe = make(map[string]Option[int])
maybe["a"] = Some(42)
maybe["b"] = None
match maybe["a"] {
Some(v) => print(v),
None => {},
}
// Missing key → None (zero bag)
match maybe["missing"] {
Some(_) => {},
None => print("absent"),
}
let mut tried = make(map[int]Result[string, string])
tried[1] = Ok("yes")
tried[2] = Err("no")
match tried[1] {
Ok(s) => print(s),
Err(e) => print(e),
}
// Named keys work too
struct Point { x: int, y: int }
let mut by_pt = make(map[Point]Option[int])
by_pt[Point { x: 0, y: 0 }] = Some(1)
}
Index-assign sets the expected type, so bare None / Err("…") match the map
value type (not a default Option[int]).
Payloads for bag values: int, string, float, bool, named struct, named enum.
Wrap a whole map when presence of the map itself is optional or fallible:
fn opt_map_demo() {
let mut m = make(map[string]int)
m["a"] = 2
let s: Option[map[string]int] = Some(m)
match s {
Some(x) => print(x["a"]),
None => {},
}
let r: Result[map[string]int, string] = Ok(m)
match r {
Ok(x) => print(x["a"]),
Err(e) => print(e),
}
}
Also works with float/bool keys and monomorphized map kinds.
fn slice_of_maps() {
let mut rows = make([]map[string]int, 0, 4)
let mut a = make(map[string]int)
a["n"] = 1
rows = append(rows, a)
print(rows[0]["n"]) // 1
}
Available for all map kinds (including bag values and nested maps):
| Helper | Role |
|---|---|
maps_keys(m) |
[]K |
maps_values(m) |
[]V (e.g. [][]int for slice values, []Option[…] for bags) |
maps_clone(m) |
shallow copy |
maps_equal(a, b) |
1 / 0 (structs/enums structural; nested maps: pointer identity) |
maps_copy(dst, src) |
copy entries into dst |
maps_clear(m) |
remove all |
fn helpers_demo() {
let mut m = make(map[string]Option[int])
m["a"] = Some(1)
m["b"] = Some(2)
let ks = maps_keys(m)
let vs = maps_values(m)
let c = maps_clone(m)
assert_eq(maps_equal(m, c), 1)
maps_clear(c)
print(len(c)) // 0
}
Pre-size with a hint: make(map[string]int, 1024).
| Need | Use |
|---|---|
| Membership set | map[K]bool + has |
| Group rows by key | map[K][]T |
| Sparse grid / matrix | map[string][][]int or nested maps |
| Optional value per key | map[K]Option[T] |
| Fallible value per key | map[K]Result[T,E] |
| Optional + fallible nest | map[K]Option[Result[T,E]] |
| Named mailbox | map[K]chan[T] |
| Optional + scalar pair | map[K](Option[T], int) |
| Optional whole table | Option[map[K]V] |
| Config tree (2–3 levels) | map[K]map[K2]V / map[K]map[K2]map[K3]V |
| File | Covers |
|---|---|
examples/testing/map_test.mko |
Core SI/II/SS |
examples/testing/map_bool_test.mko |
bool keys/values, sets |
examples/testing/map_float_test.mko |
float keys |
examples/testing/map_struct_test.mko |
struct values |
examples/testing/map_struct_key_test.mko |
struct keys, map[Struct]Struct |
examples/testing/map_enum_test.mko |
enum keys/values |
examples/testing/map_slice_test.mko |
map[K][]T |
examples/testing/map_nested_test.mko |
map[K]map[K2]V |
examples/testing/map_depth3_test.mko |
map[K]map[K2]map[K3]V |
examples/testing/map_nested_slice_test.mko |
map[K][][]T |
examples/testing/map_map_slice_test.mko |
nested maps + slice values |
examples/testing/slice_map_test.mko |
[]map / map[K][]map |
examples/testing/option_map_test.mko |
Option[map] / Result[map] |
examples/testing/map_option_result_test.mko |
bag values |
examples/testing/option_result_slice_test.mko |
[]Option[T] / []Result[T,E] |
examples/testing/map_option_slice_test.mko |
map[K][]Option[T] / map[K][]Result[T,E] |
examples/testing/map_option_of_slice_test.mko |
map[K]Option[[]T] / map[K]Result[[]T,E] |
examples/testing/map_tuple_test.mko |
map[K](T,U) scalar tuples |
examples/testing/map_tuple_struct_test.mko |
Struct/Enum tuples + 4-tuples |
examples/testing/map_option_of_map_test.mko |
map[K]Option[map] / map[K]Result[map] |
examples/testing/map_chan_test.mko |
map[K]chan[T] channel values |
examples/testing/map_slice_chan_test.mko |
map[K][]chan[T] |
examples/testing/map_option_chan_test.mko |
Option[chan] / map[K]Option[chan] / Result[chan] |
examples/testing/map_option_chan_nested_test.mko |
[]Option[chan] / Option[[]chan] maps |
examples/testing/map_chan_nested_slice_tuple_test.mko |
[][]chan / (chan, scalar) maps |
examples/testing/map_tuple_chan3_test.mko |
3-tuples with a channel field |
examples/testing/map_nested_option_chan_test.mko |
Option[Option[…]] / struct-chan 3-tuples |
examples/testing/map_option_result_nested_test.mko |
Option[Result] / triple Option / nested Result maps |
examples/testing/map_nested_bag_slice_test.mko |
nested bag slices / optional bag slices |
examples/testing/map_tuple_bag_test.mko |
Option/Result fields in map tuples |
examples/testing/nested_slice_test.mko |
[][]T |
mako test examples/testing/map_option_result_test.mko
maps_* signatures