Skip to content

Bindings

let creates an immutable binding. let permits no writes to the value, and no reassignment of the name.

let defaults = [10, 20, 30]
let timeout = 30
defaults[0] = 60write not permitted
timeout = 60reassignment not permitted

let mut creates a mutable binding. let mut permits writes to the value, and reassignment of the name.

let mut scores = [90, 85, 77]
let mut count = 0
scores[0] = 100write permitted
count += 1reassignment permitted

let mut encodes write permission in the value’s type:

let mut scores = [90, 85, 77]
scores is a mut Slice<int>
and not merely a Slice<int>

In Go, []T, map[K]V and *T allow two names to share the same data, so a write through one can change what the other sees. Lisette makes that risk visible in the type: Slice, Map and Ref are writable only when the type carries mut.

With write permission visible in the type, a function announces if it can write to its parameter, and a struct field announces if it can be written to.

See Write permission in parameters and Write permission in fields

Write permission can shrink but never grow. A name that shares data inherits the other’s permission, even under let mut.

let a = [1, 2, 3]
let mut b = areassignment allowed, but b inherits a's read-only permission
b[0] = 99error: b is read-only
let mut c = a.clone()independent copy, free to write
c[0] = 99write permitted, a untouched

const defines a compile-time constant. Only primitive values are allowed: bool, int, float64, string. The initializer must be a literal or an expression built from literals. const bindings are immutable and unaddressable.

const MAX_SIZE = 1024
const GREETING = "hello"
const DOUBLED = MAX_SIZE * 2

A tuple, struct, Slice, or Array cannot be const. Use a function that returns the value instead:

fn origin() -> Point {
Point { x: 0, y: 0 }
}

Add a type annotation with : after the binding name. On a binding it is optional, since the type usually follows from the value, unlike a function parameter, where it is required.

let x: int = 42
let y = 42

A binding can name the parts of a value instead of the whole. Write the shape of the value on the left, called a pattern, and each name in it binds to the part in that position. Tuples, structs, and enums can all be taken apart this way.

let (x, y) = (10, 20)x is 10, y is 20
let Point { x, y } = point
let Shape.Circle(radius) = shape