# Function values and closures

A function is a value. Lambdas capture by reading, and every call site is resolved while the program compiles.

## Lambdas and higher-order functions

A `fn`-typed parameter takes a lambda, written `x -> expr`, or a named function. Two or more parameters take brackets, `(a, b) -> expr`, and none at all is `() -> expr`. `map`, `filter` and `fold` in [std/arrays](https://vyrn-lang.github.io/docs/std/arrays.html) are ordinary generic functions with such a parameter.

Every use is monomorphized, so no function value survives to run time in any backend.

```vyrn
// A `fn`-typed parameter takes a lambda or a named function. Every use is
// monomorphized, so no function value survives to run time.
import { map, filter, fold } from "std/arrays"
import { joinWith } from "std/strings"

fn double(n: Int64) -> Int64 {
    return n * 2
}

export fn demo() -> String {
    let nums: Array<Int64> = [1, 2, 3, 4, 5]
    let doubled = map(nums, double)
    let evens = filter(nums, x -> x % 2 == 0)
    let total = fold(nums, 0, (acc, x) -> acc + x)

    return joinWith([
        "doubled last \{doubled[4]}",
        "evens        \{evens.length}",
        "total        \{total}",
    ], "\n")
}

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

Built output:

```
doubled last 10
evens        2
total        15
```

## Stored functions

A `fn` type is storable: a binding, a record field, an array, module state. A lambda that reads an outer local carries a copy of that local, taken where the lambda is written.

The implementation is defunctionalization: one closed enum per signature, one variant per lambda, and every call a direct call. There are no function pointers in the output.

```vyrn
// A `fn` type is storable: a let, a record field, an array. A lambda that reads
// an outer local carries a copy of it, taken where the lambda is written.
import { joinWith } from "std/strings"

type Transform = fn(Int64) -> Int64

fn makeAdder(n: Int64) -> Transform {
    return x -> x + n
}

export fn demo() -> String {
    let tenfold: Transform = x -> x * 10
    let addFive = makeAdder(5)
    let steps: Array<Transform> = [tenfold.copy(), addFive.copy()]

    let mut value = 1
    for step in steps {
        value = step(value)
    }

    return joinWith(["tenfold 4 is \{tenfold(4)}", "add five to 4 is \{addFive(4)}", "both, from 1, give \{value}"], "\n")
}

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

Built output:

```
tenfold 4 is 40
add five to 4 is 9
both, from 1, give 15
```

---

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