Pattern Matching
match: exhaustive, checked by the compiler
Section titled “match: exhaustive, checked by the compiler”fn area( s: Shape,): Double { match s { Circle(radius: r) => 3.14159 * r * r, Rectangle(width: w, height: h) => w * h, Triangle(base: b, height: h) => 0.5 * b * h, }}Positional destructuring
Section titled “Positional destructuring”match s { Circle(r) => 3.14159 * r * r, Rectangle(w, h) => w * h,}Destructuring shorthand (field punning)
Section titled “Destructuring shorthand (field punning)”When the binding variable has the same name as the field, a trailing colon
(field:) can be used instead of repeating the name (field: field):
// Long formlet Book(title: title, author: author, genre: genre) = b
// Shorthand. Equivalentlet Book(title:, author:, genre:) = bShorthand and explicit rename can be freely mixed:
let Book(title:, author: a, genre:) = b // title and genre use shorthandThe shorthand is valid in all pattern positions: let, let assert, match
arms, and for loop heads.
Discarding unmentioned fields in variant patterns
Section titled “Discarding unmentioned fields in variant patterns”A trailing .. inside a variant or record pattern means “I don’t care about
the remaining fields”. Without it, you must bind every field the type declares.
match b { Book(title:, ..) => debug title, // ignore author, genre, isbn, ...}.. is only valid at the end of the field list and binds nothing. If you want
to capture something, use ...; if you want to discard, use ...
Match guards
Section titled “Match guards”match score { n if n >= 90 => "A", n if n >= 80 => "B", _ => "F",}Wildcard _
Section titled “Wildcard _”Matches anything, binds nothing.
match weekday { Sat => true, Sun => true, _ => false,}Literal patterns
Section titled “Literal patterns”match status { "active" => "go", "paused" => "wait", _ => "unknown",}Multi-subject match
Section titled “Multi-subject match”let msg = match isAdmin, isActive { true, true => "Active admin", true, false => "Inactive admin", false, _ => "User",}OR-patterns
Section titled “OR-patterns”Multiple alternatives in a single arm. All alternatives must bind the same names with the same types.
match ticket { VIP(price: p) | Bleachers(price: p) | GeneralAdmission(price: p) => p, FreePass => 0,}Literal alternatives work too:
match status { "active" | "pending" => true, _ => false,}OR-patterns can have guards; the guard applies to the whole arm:
match ticket { VIP(price: p) | Bleachers(price: p) if p > 50 => "premium", _ => "standard",}OR-patterns are only valid as the top-level arm pattern in a single-subject
match. They are not valid in let, let assert, for, or multi-subject
match arms.
List patterns (inside match only)
Section titled “List patterns (inside match only)”match items { [] => "empty", [head, ...rest] => "starts with ${head}", [a, b, ..] => "at least two elements",}Rule of thumb: ... binds or spreads; .. discards. Three dots does something
with the rest; two dots throws it away. The same rule applies to list patterns
([head, ...rest] vs [a, b, ..]) and to variant patterns (Book(title:, ..)) ,
... has no form in variant patterns since variant fields are named, not positional.
let assert: runtime-checked single-pattern extraction
Section titled “let assert: runtime-checked single-pattern extraction”let assert Ok(value: n) = someResultlet assert Circle(radius: r) = shapeValid patterns in let assert: variant, tuple, identifier, wildcard.
List patterns and literal patterns are not valid in let assert.