# Ownership, consume, regions

A parameter states what a function does with the value. The compiler enforces it and frees the memory. There is no collector, no lifetime syntax, and no borrow annotation.

## Capabilities

A parameter carries a capability. `read` observes the value and the caller keeps it. `modify` changes it in place. `consume` takes ownership, and the caller may not name the value again.

The words are erased before the program runs. They cost nothing, and they are the only ownership syntax there is.

Use a consumed value again and the compiler names the line that took it: ``t` is used here but was already consumed by `redeem(..)` on line 7`.

```vyrn
// A parameter's capability states what the function does with the value:
// `read` observes it, `modify` changes it in place, `consume` takes it.
import { joinWith } from "std/strings"

type Ticket = { id: Int64, seats: Int64 }

fn seatCount(t: read Ticket) -> Int64 {
    return t.seats
}

fn addSeat(t: modify Ticket) {
    t.seats = t.seats + 1
}

fn redeem(t: consume Ticket) -> Int64 {
    return t.id
}

export fn demo() -> String {
    let mut t = Ticket { id: 7, seats: 1 }
    addSeat(t)
    let before = seatCount(t)
    let id = redeem(t)
    // seatCount(t) here is a compile error: `redeem` consumed t.
    return joinWith(["seats \{before}", "redeemed \{id}"], "\n")
}

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

Built output:

```
seats 2
redeemed 7
```

## Regions

A `region` block frees a group of allocations at its closing brace. It suits a loop that builds temporary values: one release for the whole block instead of one per value.

A value that must outlive the block is returned from it, and the caller owns what comes out. Storing an arena value into a binding that outlives the region is a compile error.

The editor's hover reports, for every binding, whether it is reclaimed, how, and why not when it is not.

```vyrn
// A `region` block frees a whole group of allocations at its closing brace. The
// strings built inside it go back at one known point, not at a collector's
// convenience.
export fn demo() -> String {
    let head = "line "
    let mut widest = 0

    region {
        let mut i = 0
        while i < 1000 {
            let row = head + i.toString()
            if row.byteLength > widest {
                widest = row.byteLength
            }
            i = i + 1
        }
    }

    return "1000 strings built, widest \{widest} bytes, all freed at the brace"
}

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

Built output:

```
1000 strings built, widest 8 bytes, all freed at the brace
```

---

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