# 模式匹配
`match` 是 Deft 基于形状的分派形式。它把一个值与一系列模式
解构匹配,并求值第一个匹配项的右侧。模式支持字面量、绑定、
类型测试、映射与列表解构、守卫、或模式、范围和正则。
## 快速参考
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" }
## 模式形式
### 通配符 `_`
匹配任何内容,不绑定任何值:
match $v { _ => "default" }
### 字面量模式
数字、字符串、布尔值、关键字和 `nil` 按相等性匹配:
match $status { 200 => "ok" 404 => "not found" :error => "signalled" nil => "nothing" _ => "other" }
### 变量绑定
裸 `$name` 匹配任何内容并绑定该值:
match $input { $x => echo "got: $x" }
在多个分支中复用同一绑定名以提取值:
match $entry { @{ "name" $n } => $n %{ :name $n } => $n _ => "(unknown)" }
### 类型模式
`%TypeName{ ... }` 按标签匹配带标签映射。字段解构是
可选的:
match $result { %Ok{ :value $v } => $v %Err{ :message $m } => [throw $m] } match $shape { %Point{} => "a point" %Circle{} => "a circle" _ => "something else" }
### 映射模式
`%{ ... }` 匹配包含所列键的普通映射(额外的键
没关系):
match $user { %{ :first $f :last $l :age $a } => "$f $l, age $a" %{ :name $n } => $n _ => "unknown" }
### 列表模式
`@{ ... }` 匹配列表。`&` 收集其余部分:
match $xs { @{} => "empty" @{ $first } => "one: $first" @{ $a $b } => "two: $a, $b" @{ $a & $rest } => "head: $a, rest has $rest(len) items" }
### 守卫(`when`)
用 `when` 为任何模式添加条件:
match $n { $x when ($x > 0) => "positive" $x when ($x < 0) => "negative" 0 => "zero" }
### 或模式(`|`)
在括号内用 `|` 组合备选模式:
match $status { (200 | 201 | 204) => "success" (401 | 403) => "denied" _ => "other" }
### 范围
数值范围包含两端:
match $score { 90 .. 100 => "A" 80 .. 89 => "B" 70 .. 79 => "C" _ => "F" }
范围也可与 `Ok`/`Err` 模式组合:
match $result { %Ok{ :value (70 .. 80) } => "passed in band" _ => "other" }
### 否定模式
`not` 排除某个子模式:
match $user { %{ :role (not :admin) } => "user" %{ :role :admin } => "admin" _ => "?" }
### 正则模式
`#"...":` 用 PCRE2 正则匹配字符串:
match $line { #"^ERROR: (.+)$" => "error: $it" #"^WARN: (.+)$" => "warning" _ => "other" }
## 首个匹配胜出
模式按顺序尝试。第一个匹配者胜出——把具体的用例放在一般
用例之前:
match $n { 0 => "exactly zero" $x when ($x > 0) => "positive" $x => "negative" # any remaining value }
## 匹配失败
没有匹配分支的 `match` 会抛出运行时错误。当输入空间未被
完全覆盖时,始终包含通配符 `_` 兜底:
match $input { %{ :type :click } => "clicked" %{ :type :hover } => "hovered" _ => "ignored" }
## 使用场景
### 命令分派
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 解码
def decode-user {|data| match $data { %{ :name $n :email $e } => %User{ :name $n :email $e } _ => [throw "missing fields"] } }
### 状态机
def transition {|state event| match $state $event { :idle :start => :running :running :pause => :paused :paused :resume => :running :running :stop => :idle :paused :stop => :idle _ => $state } }
### 类型安全分派
def area {|shape| match $shape { %Circle{ :radius $r } => ($math/pi * $r * $r) %Square{ :side $s } => ($s * $s) %Rectangle{ :w $w :h $h } => ($w * $h) } }
## 模式汇总
| 模式 | 匹配 |
|---|---|
| `_` | 任何内容 |
| `42`, `"hi"`, `:foo`, `nil`, `true` | 字面量相等 |
| `$x` | 任何内容,并绑定该值 |
| `%Type{ :f $v }` | 带字段的标签映射 |
| `%Type{}` | 给定类型的标签映射 |
| `%{ :k $v }` | 带键的普通映射 |
| `@{}` | 空列表 |
| `@{ $a $b }` | 恰好两项的列表 |
| `@{ $a & $rest }` | 带头部和尾部的列表 |
| `1 .. 9` | 范围内的数字(含两端) |
| `(a \| b \| c)` | 任一备选 |
| `pat when cond` | 模式加守卫 |
| `not pat` | 任何不匹配者 |
| `#"regex"` | 匹配正则的字符串 |