7Pattern Matching
A pattern describes the shape of a value. When a value matches, any variables in the pattern are bound to the corresponding parts.
7.1 Pattern Forms
| Pattern | Syntax | Matches |
|---|---|---|
| Literal | 42, "hello", true, 'A' | Exactly that value. |
| Identifier | x | Any value; binds it to x. |
| Wildcard | _ | Any value; discards it. |
| Enum (unit) | Color::Red | That variant, no payload. |
| Enum (with payload) | Shape::Circle(r) | That variant; binds the payload to r. |
| Range | '0'..'9' | Any value in the range (inclusive). |
| Or | pat | pat | pat | Any of the listed patterns. |
7.2 Enum Destructuring
type enum Shape {
Circle(f64);
Rectangle(f64, f64);
Point;
}
function describe(s: Shape) -> void {
match (s) {
Shape::Circle(r) => { printf("Circle r=%f\n", r); }
Shape::Rectangle(w, h) => { printf("Rectangle %f x %f\n", w, h); }
Shape::Point => { println("A point"); }
}
}
In each arm, the variables are introduced for the payload of that variant. The compiler enforces that the count and types match the variant's declaration.
If you don't need a payload, use _: Option::Some(_) => { ... }.
7.3 Range Patterns
Range patterns match values within an inclusive range. They are most useful for character classification. Both spellings - a..b and the explicit a..=b - are inclusive in pattern position (note this differs from a range expression, where a..b is half-open). Bounds must be integer or char literals of the same kind.
match (ch) {
'0'..='9' => { println("digit"); }
'a'..'z' | 'A'..'Z' | '_' => { println("ident-start"); }
_ => { println("other"); }
}
7.4 Guard Clauses
An arm may carry a guard: a boolean condition written if (cond) between the pattern and the =>. The guard is evaluated only after the pattern matches; if it is false, matching falls through to the next arm. Any bindings introduced by the pattern are in scope inside the guard.
match (n) {
x if (x > 100) => { 3 }
x if (x > 10) => { 2 }
x if (x > 0) => { 1 }
_ => { 0 }
}
match (o) {
Option::Some(v) if (v > 5) => { v * 10; }
Option::Some(v) => { v; }
Option::None => { -1; }
}
The parentheses around the condition are required. A guarded arm does not count toward exhaustiveness (the guard could always be false), so a match whose only arm for some case is guarded still needs a fall-through arm.
7.5 Exhaustiveness
The compiler checks that every possible value of the matched type is covered. Forgetting a variant of an enum is an error. The wildcard _ is the explicit way to opt in to a default arm.