Pattern Matching
Pattern matching with match is the primary way to inspect and destructure values in Almide. Every match must be exhaustive — the compiler verifies that all possible cases are covered.
Run this, then delete the West arm and run it again — the compiler names the
case you dropped instead of failing at runtime:
type Direction = | North | South | East | West
fn describe(d: Direction) -> String =
match d {
North => "up",
South => "down",
East => "right",
West => "left",
}
fn main() -> Unit = {
for d in [North, South, East, West] {
println(describe(d))
}
} Basic match
Section titled “Basic match”match direction { North => "up", South => "down", East => "right", West => "left",}match is an expression: it returns a value. All arms must produce the same type.
Arms are separated by commas. Each arm has the form Pattern => expr.
Pattern types
Section titled “Pattern types”Wildcard
Section titled “Wildcard”_ matches any value without binding it:
match status { 200 => "ok", 404 => "not found", _ => "other",}Identifier (binding)
Section titled “Identifier (binding)”A bare name binds the matched value to a variable:
match list.first(items) { some(x) => println("first: ${x}"), none => println("empty"),}Literal
Section titled “Literal”Match against specific values:
match command { "start" => run(), "stop" => halt(), "status" => report(), _ => err("unknown command"),}Supports Int, Float, String, and Bool literals.
match n { 0 => "zero", 1 => "one", _ => "other",}Negative literal patterns are not supported yet — the exhaustiveness checker
treats -1 as a wildcard (#897).
Use a guard instead:
match n { 0 => "zero", n if n < 0 => "negative", _ => "positive",}Option patterns
Section titled “Option patterns”some(pattern) and none destructure Option[T]:
match map.get(config, "port") { some(port) => println("port: ${port}"), none => println("using default port"),}Result patterns
Section titled “Result patterns”ok(pattern) and err(pattern) destructure Result[T, E]:
match int.parse(input) { ok(n) => n * 2, err(e) => { println("parse error: ${e}") 0 },}Constructor patterns
Section titled “Constructor patterns”Destructure variant type cases:
type Shape = | Circle(Float) | Rect{ width: Float, height: Float } | Point
fn describe(s: Shape) -> String = match s { Circle(r) => "circle with radius ${float.to_string(r)}", Rect{ width, height } => "${float.to_string(width)}x${float.to_string(height)}", Point => "point", }Unit constructors match without parentheses. Tuple constructors use CaseName(patterns...). Record constructors use CaseName{ fields... }.
Record patterns
Section titled “Record patterns”Destructure record variant cases with field names:
match shape { Rect{ width, height } => width * height, _ => 0.0,}The .. syntax allows partial matching, ignoring fields you don’t need.
Tuple patterns
Section titled “Tuple patterns”Destructure tuples directly:
match point { (0, 0) => "origin", (x, 0) => "on x-axis", (0, y) => "on y-axis", (x, y) => "at (${int.to_string(x)}, ${int.to_string(y)})",}Guards
Section titled “Guards”Add if condition after a pattern for additional constraints:
match n { x if x > 0 => "positive", x if x < 0 => "negative", _ => "zero",}When a guard is false, the next arm is tried:
fn classify(score: Int) -> String = match score { n if n >= 90 => "A", n if n >= 80 => "B", n if n >= 70 => "C", _ => "F", }Guards can use any boolean expression:
match item { some(s) if string.len(s) > 0 => process(s), some(_) => err("empty string"), none => err("missing"),}Exhaustiveness
Section titled “Exhaustiveness”The compiler ensures every possible value is covered. Missing cases are compile errors:
type Color = Red | Green | Blue
match color { Red => "red", Green => "green", // Compile error: non-exhaustive match, missing: Blue}Use _ as a catch-all when you don’t need to handle every case individually:
match color { Red => "red", _ => "not red",}Pipe into match
Section titled “Pipe into match”The pipe operator can feed a value directly into match:
list.get(args, 1) |> match { some(cmd) => cmd, none => "help",}Nested patterns
Section titled “Nested patterns”Patterns can be nested to match complex structures:
match result { ok(some(value)) => use(value), ok(none) => default(), err(e) => handle(e),}Next steps
Section titled “Next steps”- Types & Values — variant types and records
- Error Handling — matching on Result and Option
- Control Flow — if-then-else and guard