Pattern Matching
Pattern matching in Aria is exhaustive — the compiler rejects incomplete matches. Patterns appear in match expressions, for loops, variable bindings, and catch blocks.
Match Expressions
fn describe(s: Shape) -> str = match s {
Circle{radius} => "circle with radius {radius}"
Rect{w, h} => "{w}x{h} rectangle"
Point => "a point"
} If you add a new variant to Shape, every match on it becomes a compile error (E0400) until updated. This is critical for AI-generated code — the compiler catches incomplete handling automatically. Exhaustiveness checking covers sum types, booleans, Option, and Result.
Or-Patterns
Match multiple patterns in a single arm with |:
match direction {
North | South => "vertical"
East | West => "horizontal"
}
match statusCode {
200 | 201 | 204 => "success"
400 | 422 => "client error"
500 | 502 | 503 => "server error"
code => "other: {code}"
} Named Patterns with @
Bind a name to a matched value while also matching its structure:
match shape {
s @ Circle{radius} if radius > 10.0 => {
println("large circle: {s}")
}
_ => println("other shape")
} Guards
msg := match temperature {
t if t < 0 => "freezing"
t if t < 20 => "cold"
t if t < 30 => "comfortable"
_ => "hot"
} Nested Patterns
match response {
Ok(Some(user)) => greet(user)
Ok(None) => println("no user found")
Err(e) => println("error: {e}")
} Destructuring in Bindings
// Tuple destructuring
(lo, hi) := minMax(list)
// Struct destructuring
Point{x, y} := getOrigin()
// In for loops
for (index, value) in items.enumerate() {
println("{index}: {value}")
}
for (key, value) in config {
println("{key} = {value}")
} Option Patterns
match findUser(id) {
Some(user) => process(user)
None => println("not found")
}
// Or use optional chaining
name := user?.profile?.displayName ?? "Anonymous" Array & Slice Patterns
Destructure arrays and match on their structure:
match items {
[] => println("empty")
[only] => println("single: {only}")
[first, ..rest] => {
println("first: {first}, remaining: {rest.len()}")
}
} Refutable Bindings
Use pattern matching in bindings with an else fallback for when the pattern doesn't match:
Some(user) := findUser(id) else {
println("user not found")
return
}
// user is now bound and available Float Patterns
Match on floating-point literals:
match value {
0.0 => "zero"
1.0 => "one"
x => "{x}"
} Wildcard Pattern
match command {
"quit" => exit(0)
"help" => showHelp()
cmd => println("unknown command: {cmd}")
}
// Discard with _
match result {
Ok(_) => println("success")
Err(e) => println("failed: {e}")
}