# Values and mutation


Everything in Xo is a value: assigning or passing a struct copies it (cheaply,
because collections share structure). There are no pointers, so two parts of
a program can never change the same value without synchronization, and data
races cannot happen.

`mutation/main.xo`

```xo
struct Account { owner: Str, balance: Int }

fn (var a: Account) deposit(amount: Int) requires amount > 0 {
  a.balance += amount
}

fn main(os: Os) {
  var acct = Account{owner: "ada", balance: 10}
  let snapshot = acct
  acct.deposit(5)
  os.stdio.println("now ${acct.balance}, snapshot ${snapshot.balance}")

  var accounts: Map[Str, Account] = {"ada": acct}
  accounts.update("ada", Account{owner: "ada", balance: 0}, fn(var a) { a.deposit(100) })
  let stored = accounts.get("ada").map(fn(a) { a.balance }) ?? 0
  os.stdio.println("stored ${stored}")

  let hits = Atomic[Int].new(0)
  let cache = Mutex[Map[Str, Int]].new({})
  cache.with(fn(var m) { m.put("k", hits.add(1)) })
  let size = cache.with_read(fn(m) { m.len() })
  os.stdio.println("hits ${hits.get()}, cache ${size}")
}
```

Output:

```text
now 15, snapshot 10
stored 115
hits 1, cache 1
```



- `snapshot` kept the old balance: `acct` and `snapshot` are separate values.
- A `var` receiver (`fn (var a: Account)`) changes the caller's binding in
  place.
- `m.update(key, init, fn(var v) { ... })` changes a value inside a
  collection in one step. Copying a value out, changing it, and forgetting to
  store it back is a compile error (`XO0520`).
- `Mutex[T]` and `Atomic[T]` are the only shared mutable state.
  `with` gives the closure the value to change; `with_read` gives read only
  access shared with other readers.

Closures capture by value, so they cannot quietly change a local:

```xo
fn main(os: Os) {
  var count = 0
  let bump = fn() { count += 1 }
  bump()
  os.stdio.println("${count}")
}
```

`xo check` says:

```text
main.xo:3:21: error XO0502: assignment mutates `count`, which is captured by a closure; closures capture by value (core 3.3)
  note: main.xo:2:7: `count` is declared here, outside the closure
  note: to share mutable state with a closure, capture a `Mutex` or `Atomic` handle (core 5.4)
1 module(s), 1 error(s), 0 warning(s)
```


