# Pattern Matching
`match` is Deft's shape-based dispatch form. It deconstructs a value
against a series of patterns and evaluates the right-hand side of the
first match. Patterns support literals, bindings, type tests, map and
list destructuring, guards, or-patterns, ranges, and regex.
## Quick Reference
match $value { _ => "anything" 42 => "the answer" $x => "bound: $x" %Point{ :x $x } => "point at x=$x" @{ $first & $rest } => "first: $first" $n when ($n > 0) => "positive" (1 | 2 | 3) => "low" 1 .. 9 => "single digit" %Err{ :message $m } => "error: $m" }
## Pattern Forms
### Wildcard `_`
Matches anything, binds nothing:
match $v { _ => "default" }
### Literal patterns
Numbers, strings, booleans, keywords, and `nil` match by equality:
match $status { 200 => "ok" 404 => "not found" :error => "signalled" nil => "nothing" _ => "other" }
### Variable binding
A bare `$name` matches anything and binds the value:
match $input { $x => echo "got: $x" }
Reuse the same binding name in multiple branches to extract a value:
match $entry { @{ "name" $n } => $n %{ :name $n } => $n _ => "(unknown)" }
### Type patterns
`%TypeName{ ... }` matches a tagged map by tag. Field destructuring is
optional:
match $result { %Ok{ :value $v } => $v %Err{ :message $m } => [throw $m] } match $shape { %Point{} => "a point" %Circle{} => "a circle" _ => "something else" }
### Map patterns
`%{ ... }` matches a plain map containing the listed keys (extra keys
are fine):
match $user { %{ :first $f :last $l :age $a } => "$f $l, age $a" %{ :name $n } => $n _ => "unknown" }
### List patterns
`@{ ... }` matches lists. `&` collects the rest:
match $xs { @{} => "empty" @{ $first } => "one: $first" @{ $a $b } => "two: $a, $b" @{ $a & $rest } => "head: $a, rest has $rest(len) items" }
### Guards (`when`)
Add a condition to any pattern with `when`:
match $n { $x when ($x > 0) => "positive" $x when ($x < 0) => "negative" 0 => "zero" }
### Or-patterns (`|`)
Combine alternative patterns with `|` inside parens:
match $status { (200 | 201 | 204) => "success" (401 | 403) => "denied" _ => "other" }
### Ranges
Numeric ranges match inclusive of both ends:
match $score { 90 .. 100 => "A" 80 .. 89 => "B" 70 .. 79 => "C" _ => "F" }
Ranges also compose with `Ok`/`Err` patterns:
match $result { %Ok{ :value (70 .. 80) } => "passed in band" _ => "other" }
### Negative patterns
`not` excludes a sub-pattern:
match $user { %{ :role (not :admin) } => "user" %{ :role :admin } => "admin" _ => "?" }
### Regex patterns
`#"...":` matches a string against a PCRE2 regex:
match $line { #"^ERROR: (.+)$" => "error: $it" #"^WARN: (.+)$" => "warning" _ => "other" }
## First Match Wins
Patterns are tried in order. The first match wins — put specific cases
before general ones:
match $n { 0 => "exactly zero" $x when ($x > 0) => "positive" $x => "negative" # any remaining value }
## Match Failure
A `match` with no matching branch throws a runtime error. Always
include a wildcard `_` fallback when the input space isn't fully
covered:
match $input { %{ :type :click } => "clicked" %{ :type :hover } => "hovered" _ => "ignored" }
## Use Cases
### Command dispatch
def handle {|cmd args| match $cmd { "open" => [open-file $args~path] "save" => [save-file $args~path $args~content] "quit" => [shutdown] _ => [throw "unknown command: $cmd"] } }
### JSON decoding
def decode-user {|data| match $data { %{ :name $n :email $e } => %User{ :name $n :email $e } _ => [throw "missing fields"] } }
### State machines
def transition {|state event| match $state $event { :idle :start => :running :running :pause => :paused :paused :resume => :running :running :stop => :idle :paused :stop => :idle _ => $state } }
### Type-safe dispatch
def area {|shape| match $shape { %Circle{ :radius $r } => ($math/pi * $r * $r) %Square{ :side $s } => ($s * $s) %Rectangle{ :w $w :h $h } => ($w * $h) } }
## Patterns Summary
| Pattern | Matches |
|---|---|
| `_` | Anything |
| `42`, `"hi"`, `:foo`, `nil`, `true` | Literal equality |
| `$x` | Anything, binds the value |
| `%Type{ :f $v }` | Tagged map with field |
| `%Type{}` | Tagged map of given type |
| `%{ :k $v }` | Plain map with key |
| `@{}` | Empty list |
| `@{ $a $b }` | List of exactly two |
| `@{ $a & $rest }` | List with head and rest |
| `1 .. 9` | Number in range (inclusive) |
| `(a \| b \| c)` | Any of the alternatives |
| `pat when cond` | Pattern plus guard |
| `not pat` | Anything not matching |
| `#"regex"` | String matching regex |