Skip the bullshit
// docs / Language

Functions and objects

Closures, methods and interfaces. ChatGPT said we were missing them, so here they are.

Closures

vcwl
fn make_adder(n: Int) -> fn(Int) -> Int {
|x| x + n // captures a copy of n
}
let add2 = make_adder(2)
add2(40) // 42
let done = todos.filter(|t| t.done)
let titles = todos.map(|t| t.title).join(", ")
let total = prices.fold(0.0, |sum, p| sum + p)
let sorted = people.sort_by(|a, b| a.age < b.age)

Parameter and return types are inferred from where the closure goes, or written out: |a: Int, b: Int| -> Int { a + b }. Function types look like fn(String) -> Bool, named functions are values too (xs.map(double)), and arrays have map, filter, fold, each, any, all, find and sort_by.

→

Closures capture copies of what they use, component state included: a view that filters with a closure updates when the state it captured changes.

→

They cannot assign to captured variables or state; return the new value instead. return inside a closure returns from the closure.

→

A struct field or component property can hold a function: Tag(n: n, format: |x| "#{x}"), and button.on_press() calls it.

Methods

vcwl
impl Vec2 {
fn new(x: Int, y: Int) -> Self { // no self: Vec2.new(1, 2)
Vec2 { x: x, y: y }
}
fn add(self, o: Vec2) -> Vec2 { // v.add(w)
Vec2.new(self.x + o.x, self.y + o.y)
}
}
impl Stack<T> { // generic types name their parameters
fn top(self) -> T? { self.items.last() }
}

Interfaces

vcwl
interface Shape {
fn area(self) -> Float
fn name(self) -> String
}
impl Shape for Circle {
fn area(self) -> Float { 3.14159 * self.r * self.r }
fn name(self) -> String { "circle" }
}
let shapes: [Shape] = [Circle { r: 1.0 }, Square { side: 2.0 }]
let total = shapes.fold(0.0, |sum, s| sum + s.area())

A value turns into an interface it implements wherever the interface is expected: arguments, annotated lets, array elements, struct fields, return values. A missing or mistyped method is a compile error that spells out the signature you owe.