# Lists, maps, and sets


`collections/main.xo`

```xo
fn show(xs: List[Int]) -> Str {
  xs.map(fn(x) { "${x}" }).join(" ")
}

fn main(os: Os) {
  var xs = [3, 1, 2]
  xs.push(5)
  let doubled = xs.map(fn(x) { x * 2 })
  let small = xs.filter(fn(x) { x < 3 })
  let total = xs.fold(0, fn(acc, x) { acc + x })
  os.stdio.println("sorted: ${show(xs.sort())}")
  os.stdio.println("doubled: ${show(doubled)}, small: ${show(small)}, total: ${total}")

  var ages: Map[Str, Int] = {"ada": 36}
  ages.put("grace", 85)
  ages["linus"] = 28
  let age = ages.get("ada") ?? 0
  os.stdio.println("ada is ${age}, ${ages.len()} people")
  for (name, a) in ages {
    os.stdio.println("${name}: ${a}")
  }

  var seen = ["x"].to_set()
  seen.add("x")
  seen.add("y")
  os.stdio.println("${seen.len()} unique")
}
```

Output:

```text
sorted: 1 2 3 5
doubled: 6 2 4 10, small: 1 2, total: 11
ada is 36, 3 people
ada: 36
grace: 85
linus: 28
2 unique
```



- `List`, `Map`, and `Set` are immutable and persistent. `push` and `put` on a
  `var` rebind it to a new collection that shares structure with the old one,
  so copies are cheap and nothing changes behind your back.
- Maps and sets keep insertion order.
- `map`, `filter`, `fold`, `find`, `sort`, and friends are methods.
- A list does not implement `Display`, so `show` formats it explicitly. The
  compiler says so if you try to interpolate one.

Reading a map by index is the map version of a nil dereference, so Xo
rejects it:

```xo
fn main(os: Os) {
  let ages = {"ada": 36}
  let a = ages["ada"]
  os.stdio.println("${a}")
}
```

`xo check` says:

```text
main.xo:3:11: error XO0410: reading a Map by index faults when the key is missing
  note: use `m.get(k)` (an optional) or `m.get_or_fault(k, "why the key must exist")` (core 3.6)
  fix: use get_or_fault
1 module(s), 1 error(s), 0 warning(s)
```


