# Collections and Map

Arrays and maps are subject-first: the value comes before the verb. A lookup answers `Option`, so a missing entry is a case you handle.

## Arrays

An array grows with `push`, is read with `xs[i]`, and reports `xs.length`. An element store writes in place, and the index is checked.

`pop()` answers `Option<T>`, because an empty array has nothing to give. [std/arrays](https://vyrn-lang.github.io/docs/std/arrays.html) adds `map`, `filter`, `fold`, `any`, `all` and `sortBy`.

```vyrn
// An array is subject-first: `xs.push(x)`, `xs[i]`, `xs.length`, `xs.pop()`.
// `pop` answers `Option`, because an empty array has nothing to give.
import { joinWith } from "std/strings"

export fn demo() -> String {
    let mut xs: Array<Int64> = [1, 2, 3]
    xs.push(4)
    xs[0] = 10

    let mut total = 0
    for x in xs {
        total = total + x
    }

    let last = match xs.pop() {
        Some(v) => v.toString(),
        None => "nothing",
    }

    return joinWith(["length \{xs.length}", "total \{total}", "popped \{last}"], "\n")
}

fn main() -> Int64 {
    print(demo())
    return 0
}
```

Built output:

```
length 3
total 19
popped 4
```

## Map

`Map<String, V>` keeps insertion order. `m[k]` answers `Option<V>`, `m[k] = v` inserts or updates, and an update keeps the key where it was.

On the wire a map is a JSON object, and its schema is `additionalProperties`. A validated value type re-runs its rule on every insert.

```vyrn
// `Map<String, V>` keeps insertion order. A lookup answers `Option<V>`, so a
// missing key is a value you handle and never a null you forget.
import { joinWith } from "std/strings"

fn score(m: Map<String, Int64>, k: String) -> String {
    return match m[k] {
        Some(v) => v.toString(),
        None => "none",
    }
}

export fn demo() -> String {
    let mut scores: Map<String, Int64> = [:]
    scores["ada"] = 5
    scores["grace"] = 8
    scores["ada"] = 6 // an update keeps the original slot

    let mut order: Array<String> = []
    for k in scores.keys() {
        order.push(k)
    }
    let keys = joinWith(order, ", ")
    let ada = score(scores, "ada")
    let hopper = score(scores, "hopper")

    return joinWith([
        "keys    \{keys}",
        "ada     \{ada}",
        "hopper  \{hopper}",
        "length  \{scores.length}",
    ], "\n")
}

fn main() -> Int64 {
    print(demo())
    return 0
}
```

Built output:

```
keys    ada, grace
ada     6
hopper  none
length  2
```

---

From https://vyrn-lang.github.io/guide/collections.html — generated by `site/export.vyrn` from the Vyrn repository.
