Skip to Content

Pattern

A pattern is a description of a value’s shape. match arms, if val, while val, expect, for iteration variables, and destructuring bindings all share one pattern machinery; this page lists all of it in one place.

Forms at a Glance

FormNameDescription
_wildcardMatches anything, binds nothing
namebindingAlways matches; binds an immutable value
val name / var nameexplicit bindingDeclares read-only / mutable respectively
42 -42 3.14 "lit" 'c' true nullliteralMust agree with the scrutinee’s category
1..=10rangelo..hi half-open, lo..=hi closed; one bound may be omitted
A | BorEach alternative must have the same binding set (MS4005)
A & BandBoth patterns must match
Type(p1, p2)type (positional payload)Tests the type and deconstructs by position
Type { field: p, field2, .. }type (named payload)The shorthand field2 equals field2: field2; .. ignores the remaining fields
name @ patternsub-bindingBinds the whole value to name while matching the inner pattern
(p1, p2)tupleDeconstructs by position
[a, b]list (prefix)The length must match exactly
[x, ..rest]list (rest)rest binds a copied array of the remaining elements
[x, ..] / [..] / []list (ignore / any / empty)See below
Pkg::Mod.Type(...)qualified typeA type qualified within the same package or across packages
{ kind: 1, hp: h, .. }anonymous recordThe scrutinee must be a data value (MS3271)

Literals, Ranges, and Or

for n in [5, 42, 95, 300] { print(n, match n { 5 | 42 => "the answer or five", 90..=100 => "ninety-plus tier", v @ 101..=299 => $"middle band {v}", _ => "the rest", }); }
5 the answer or five 42 the answer or five 95 ninety-plus tier 300 the rest

v @ 101..=299 binds the whole value into v while requiring it to fall inside the range. Neither side of an or pattern may carry bindings (or each side must carry exactly the same binding set); otherwise it raises MS4005.

Tuples

val pair = (1, "a"); match pair { (n, s) => print($"number {n}: {s}"), } val (m, tag) = pair; print(m, tag);
number 1: a 1 a

The destructuring binding val (a, b) = expr is a pattern’s first application outside match: the left side of the equals sign is a pattern.

Tuple values on the any channel support type-shape checks: if e is (int, string) p decides at runtime by component count plus per-element recursion, binding the tuple value to p on a hit, while a shape mismatch quietly yields False. Nested shapes and nullable elements take part too ((int?, string) matches a null).

var e: any = (1, "a"); if e is (int, string) p { print(p.Item1); }
a

List Patterns

The scrutinee must be a list<T> or an array. A prefix pattern requires the length to match exactly; ..rest binds the remaining elements as a copied array; a lone .. means “ignore everything after this point”; [] matches only the empty list:

func Classify(xs: list<int>) -> string { return match xs { [] => "empty list", [only] => $"single element {only}", [a, b] => $"a pair {a} and {b}", [first, ..rest] => $"first {first}, plus {rest.Count} more", _ => "fallback", }; } print(Classify(new list<int>())); print(Classify([7])); print(Classify([1, 2])); print(Classify([1, 5, 9, 12]));
empty list single element 7 a pair 1 and 2 first 1, plus 3 more
  • rest is an independent copied array: binding copies the remaining elements, writes to rest[i] change only the copy, the original list is unaffected, and later mutation of the original list is not reflected in rest.
  • .. may appear only in the last element position; the middle form [a, .., b] is not supported.
  • Nested list patterns ([[a], ..]) are legal.
  • List patterns never count toward exhaustiveness: [..] looks like it matches any list, but the exhaustiveness check gives it no coverage; match still needs a _ fallback.

Destructuring bindings accept list patterns too:

val xs = [10, 20, 30, 40]; val [head, ..tail] = xs; print(head, tail);
10 [20, 30, 40]

Notes

  • A literal pattern whose category differs from the scrutinee’s raises MS4002 (matching "x" or true against an int value, say); integer literals do adapt to floats.
  • Float literal patterns ignore suffixes: 0.3, 0.3f32, and 0.3f16 are judged the same, compared after rounding to the scrutinee’s width.
  • The iteration-variable slot of for is a pattern slot; for (k, v) in pairs destructures directly.
Last updated on October 11, 2026