Tutorial: Pattern Matching
Pattern matching lets you destructure and inspect data elegantly.
Basic Patterns
Literal Patterns
Match exact values:
lumen
cell describe(n: Int) -> String
match n
0 -> return "zero"
1 -> return "one"
2 -> return "two"
_ -> return "many" # Wildcard (default)
end
endBoolean Patterns
lumen
cell bool_word(b: Bool) -> String
match b
true -> return "yes"
false -> return "no"
end
endBinding Patterns
Capture the matched value:
lumen
cell sign(n: Int) -> String
match n
0 -> return "zero"
x if x > 0 -> return "positive: {x}"
x -> return "negative: {x}"
end
endGuards
Add conditions with if:
lumen
cell categorize(n: Int) -> String
match n
x if x < 0 -> return "negative"
x if x == 0 -> return "zero"
x if x < 10 -> return "single digit"
x if x < 100 -> return "double digit"
_ -> return "large"
end
endDestructuring
Tuples
lumen
cell describe_point(point: tuple[Int, Int]) -> String
match point
(0, 0) -> return "origin"
(x, 0) -> return "on x-axis at {x}"
(0, y) -> return "on y-axis at {y}"
(x, y) -> return "at ({x}, {y})"
end
endLists
lumen
cell describe_list(items: list[Int]) -> String
match items
[] -> return "empty"
[x] -> return "single element: {x}"
[x, y] -> return "two elements: {x} and {y}"
[first, ...rest] -> return "first is {first}, {length(rest)} more"
end
endRecords
lumen
record Point
x: Int
y: Int
end
cell quadrant(point: Point) -> String
match point
Point(x: 0, y: 0) -> return "origin"
Point(x: x, y: y) if x > 0 and y > 0 -> return "Q1"
Point(x: x, y: y) if x < 0 and y > 0 -> return "Q2"
Point(x: x, y: y) if x < 0 and y < 0 -> return "Q3"
Point(x: x, y: y) if x > 0 and y < 0 -> return "Q4"
_ -> return "on axis"
end
endShorthand with .. to ignore other fields:
lumen
record User
id: Int
name: String
email: String
active: Bool
end
cell check_status(user: User) -> String
match user
User(active: true, ..) -> return "Active user"
User(active: false, ..) -> return "Inactive user"
end
endEnum Patterns
Simple Enums
lumen
enum Color
Red
Green
Blue
end
cell hex(color: Color) -> String
match color
Red -> return "#FF0000"
Green -> return "#00FF00"
Blue -> return "#0000FF"
end
endEnums with Data
lumen
enum Result
Ok(value: Int)
Err(message: String)
end
cell handle(result: Result) -> String
match result
Ok(value) -> return "Success: {value}"
Err(msg) -> return "Error: {msg}"
end
endNested Enum Patterns
lumen
enum Option
Some(value: Int)
None
end
enum Result
Ok(opt: Option)
Err(msg: String)
end
cell extract(result: Result) -> Int
match result
Ok(Some(value)) -> return value
Ok(None) -> return 0
Err(_) -> return -1
end
endOr Patterns
Match multiple patterns:
lumen
cell is_vowel(c: String) -> Bool
match c
"a" | "e" | "i" | "o" | "u" -> return true
_ -> return false
end
endType Patterns
Check types in unions:
lumen
cell describe(value: Int | String | Bool) -> String
match value
n: Int -> return "Integer: {n}"
s: String -> return "String: {s}"
b: Bool -> return "Boolean: {b}"
end
endWildcard Pattern
The _ pattern matches anything:
lumen
cell first_digit(n: Int) -> Int
match n
0 -> return 0
1 -> return 1
_ -> return 9 # Everything else
end
endUse _ to ignore parts:
lumen
cell second(items: list[Int]) -> Int | Null
match items
[_, x, ...] -> return x
_ -> return null
end
endMatch Expressions
Match can be used as an expression:
lumen
cell grade_label(score: Int) -> String
let label = match score
s if s >= 90 -> "A"
s if s >= 80 -> "B"
s if s >= 70 -> "C"
s if s >= 60 -> "D"
_ -> "F"
end
return label
endComplex Example
A calculator with pattern matching:
lumen
enum Expr
Number(value: Float)
Add(left: Expr, right: Expr)
Subtract(left: Expr, right: Expr)
Multiply(left: Expr, right: Expr)
Divide(left: Expr, right: Expr)
end
cell evaluate(expr: Expr) -> Float | Null
match expr
Number(n) -> return n
Add(left, right) -> return (evaluate(left) ?? 0.0) + (evaluate(right) ?? 0.0)
Subtract(left, right) -> return (evaluate(left) ?? 0.0) - (evaluate(right) ?? 0.0)
Multiply(left, right) -> return (evaluate(left) ?? 0.0) * (evaluate(right) ?? 0.0)
Divide(left, right) ->
let r = evaluate(right) ?? 0.0
if r == 0.0
return null
end
return (evaluate(left) ?? 0.0) / r
end
end
cell main() -> String
let expr = Add(
Number(5.0),
Multiply(Number(3.0), Number(4.0))
)
match evaluate(expr)
n: Float -> return "Result: {n}"
null -> return "Evaluation error"
end
endMatch Exhaustiveness
The compiler checks that match statements on enum subjects cover all variants. Missing variants produce compile errors:
lumen
enum Direction
North
South
East
West
end
cell label(d: Direction) -> String
match d
North -> return "up"
South -> return "down"
# Compile error: IncompleteMatch — missing East, West
end
endA wildcard _ or catch-all identifier pattern makes any match exhaustive. Guard patterns do not contribute to exhaustiveness coverage.
Best Practices
- Be exhaustive — Cover all cases or use
_as fallback; the compiler checks enum coverage - Order matters — First matching pattern wins
- Use guards for complex conditions — Keep patterns simple
- Destructure in the pattern — Don't extract then check
Next Steps
- Error Handling — Using result types
- AI-Native Tutorial — Tools and grants