# 模式匹配 `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"` | 匹配正则的字符串 |