Language Policy

Bindings, Scope & Closures

Canonical grammar, semantics, constraints, and deferred boundaries for Bindings, Scope & Closures.

Bindings make mutability, compile-time evaluation, destructuring, lexical lifetime, shadowing, and closure capture explicit instead of deriving them from assignment accidents.

Policy

let pattern = expression creates immutable lexical bindings and may destructure only where the pattern is valid. let mut name = expression creates one mutable cell and accepts only a bare identifier. const name = const-expression is evaluated under the restricted constant grammar. Scopes are lexical; an inner block may shadow an outer name, but one scope cannot redeclare the same name.

Specified behavior

An immutable capture remains read-only. A lambda that captures a mutable binding observes the same cell, so valid assignments remain visible across calls and the cell lives as long as any closure needs it. Pattern bindings are immutable and exist only in their success or iteration scope. using name = fileExpression { body } creates one immutable child-scope File binding and registers its implicit close after successful acquisition.

Constraints and loud decline

mut let is rejected; only let mut is canonical. Immutable let, const, parameters, and pattern bindings cannot be assigned. using accepts one bare unannotated name and one checked File only—no destructuring, multiple resources, mutable binding, as, general close protocol, or expression result. A refutable pattern cannot be smuggled into ordinary let unless that binding position proves it irrefutable.

Deferred boundary

Explicit capture lists, move capture, Rust closure traits, borrow receivers, general disposable protocols, asynchronous cleanup, and post-close host-exception guarantees are outside this contract. Closures preserve lexical Topaz cells, not target-language ownership syntax.

Worked example

TOPAZ
function makeAdder(base: int) -> (int) -> int {
    return value => value + base
}

const DEFAULT_STEP = 5
let addStep = makeAdder(DEFAULT_STEP)
let mut total = 0
total = addStep(total)