# XO0908: an element counted up and down each iteration

Reported by `xo vet --cost`, which builds the program and reads what the compiler did. A named function that only reads a parameter borrows it, so passing it a list element costs nothing. A function value (a closure, a `fn` parameter) borrows its arguments too (decision 0337), except one whose type is the function's result type (or one of a tuple result's: an accumulator, a `var` closure's value), which it takes so the body can update it in place: each element passed there is counted up before the call and down after, atomically when the collection is shared across threads. Call a named function that only reads the element, return another type, or hoist the call out of the loop. The prelude's `map`, `filter`, `find`, `any`, `all`, and `fold` hand every element to their function value the same way, so `xs.map(fn(u: User) -> User { ... })` over elements holding heap memory is noted at the call, and `xs.any(fn(u) { u.name == n })` is not; a `for` loop over the list borrows its elements (decision 0186).

## Example

```xo
fn total(xs: List[Str], f: fn(Str) -> Str) -> Int {
  var t = 0
  for x in xs {
    t += f(x).len()
  }
  t
}
```

## Fix

```xo
fn width(s: Str) -> Int {
  s.len()
}

fn total(xs: List[Str]) -> Int {
  var t = 0
  for x in xs {
    t += width(x)
  }
  t
}
```

Run `xo explain XO0908` for this text in a terminal, or see
[section 10.6 of the specification](../../spec/core/#106-diagnostic-codes).

