Skip to content

Patterns, bindings, and guards

Pattern = "." identifier [ "(" [ identifier { "," identifier } ] ")" ]
| "(" identifier ":" Type ")" | literal | "nil" | "default" .
Arm = Pattern [ "if" Expression ] ( Block | "=>" Expression ) .

A case pattern selects a union/ref-union/enum case. Its positional bindings correspond to payloads in case declaration order and are immutable names scoped solely to that arm. A single binding on a value-union case may be a case view: its declared payload members are projected through that binding; for a single payload the view is transparent and also behaves as the payload value.

union Event { entry(level: int, text: string), closed }
match event {
.entry(v) if v.level > 2 => v.text
.entry(_, text) => text
.closed => "closed"
}

A type pattern (name: T) performs an is T test and binds the narrowed value on success. It is valid for an open reference/interface/object scrutinee, while a closed union/enum uses case patterns. nil matches the absent branch of a nullable/reference scrutinee. Literals match int, string, or bool by value.

A guard evaluates only after its pattern matches and bindings exist. If false, control proceeds to the next arm. It therefore never supplies unconditional coverage for exhaustiveness.