模式与匹配:参考级全景 — 第 19 章拆解
模式与匹配:参考级全景
这一章讲什么: 第 6 章用了 match,本章把"模式"这个主题讲全—— 模式不只是 match 的配件:let 的左边、函数参数、for 循环的变量,全是模式。 读完你会得到:一张"什么位置允许什么模式"的判定表,和全部模式语法的速查。 这一章定位是参考章:不必通记,知道每个武器存在、回得来查即可。
1. 顶层全景:模式出现在哪
let PATTERN = 表达式 → 只许"不可失败"的模式
fn f(PATTERN: T) / 闭包参数 → 只许不可失败
for PATTERN in ... → 只许不可失败
match / if let / while let / let...else → 可失败
(match 要求穷尽;if let 系不检查穷尽)
图说:左边一列是"匹配失败就没法继续"的地方,所以只许总能成功的模式;
右边一列是"为失败准备了出路(别的臂/else)"的地方,允许可失败模式。let x = 5 的 x 就是模式(把匹配到的一切绑给 x);let (x, y, z) = (1, 2, 3) 是元组解构——元素个数对不上直接 E03081。if let 链可以混 else if 普通条件和 else if let 不同模式——比 match 灵活,但失去穷尽性检查(漏了 else 编译器不吱声)2。while let 循环:"模式还匹配就继续"(第 17 章的 while let Some(v) = rx.recv().await 就是用它)3。for 循环的 (index, value) 模式配 enumerate,是最常用的解构之一4。
2. Refutability:模式可能失败吗
不可失败(irrefutable)模式:对任何值都能匹配(x、_、(x, y))。可失败(refutable)模式:对某些值会失配(Some(x) 遇 None 即失败)。
规则一句话:匹配失败时程序"无处可去"的位置,只许不可失败模式。把 let Some(x) = opt; 写进 let 会吃 E0005(refutable pattern in local binding)——因为 None 来了没法办。出路是 let Some(x) = opt else { return };(let...else 接受可失败模式,else 必须发散);反过来,给 let...else 一个永远匹配的模式,编译器警告"else 是死代码"5。
3. 模式语法速查
匹配字面量:1 => ...。 多个模式:1 | 2 => ...(或运算符)。 范围:1..=5 => ...、'a'..='j' => ...——闭区间,只允许数字和 char(编译期要能判空)6。
解构:结构体 Point { x, y }(字段名简写);枚举 Some(i)、Message::Move { x, y };混合:Point { x, y: 0 } 只对 y 做字面量测试、x 照样绑变量7。元组、嵌套引用皆可解构。
忽略值的四种姿势(本章的一半篇幅):
| 写法 | 干什么 | 绑不绑定 |
|---|---|---|
_ | 匹配任意值、整条臂忽略 | 不绑定(值不被 move) |
_ 嵌在模式里 | 只忽略一部分,如 Some(_) | 不绑定 |
_x(下划线开头名字) | 占位但绑定值(会 move!) | 绑定 |
.. | 忽略剩余所有部分,如 Point { x, .. } | 不绑定 |
区别有实战后果:if let Some(_s) = s 会把 String move 进 _s,后面再用 s 报错;Some(_) 则不碰所有权。.. 每个元组模式只能出现一次——(.., second, ..) 有二义性,编译错8。
Match guard(匹配守卫):Some(n) if n == y => ...——模式后面跟 if 附加条件。两个要点:
① guard 里用的是外层变量(不引入新绑定),这正是"模式变量遮蔽外层同名变量"问题的解法——Some(y) 会遮蔽外面的 y,Some(n) if n == y 不会9。
② 有 guard 时编译器不做穷尽性检查(条件无法静态枚举)。guard 对 | 组合的模式整体生效:4 | 5 | 6 if y 等价于 (4 | 5 | 6) if y,不是 4 | 5 | (6 if y)10。
@ 绑定:id @ 3..=7 => ...——一边测范围一边把值存进变量。不用 @,要么只测范围(值丢了),要么只绑值(没测)11。
4. 作者的判断与证据
- "大多数情况不用操心 refutability,认识它是为了看懂报错"——本章自我定位:参考章12。
- "模式变量遮蔽是 match/if let 的新作用域所致"——机制说明,配了 Some(y) 的经典反例9。
判断(我们的,不是书里的): 本章的一个隐藏主线是"绑定的边界=所有权的边界": 每个模式都要问一句"这个变量绑走值了吗"——
_不绑(值留着),_x绑(值 move 走),ref模式借,@边测边绑。模式语法的复杂度,一半是所有权语义逼出来的。 带着这个问题读语法表,每一行都有理由。 如果错,会错在: "绑定即 move"只对非 Copy 类型成立;Copy 类型(_x)只是复制,不夺所有权—— 文中 String 的例子是非 Copy 场景,读的时候别外推到 i32。
5. 边界与局限
- guard 不做穷尽性检查是明确的取舍,没有给替代方案(只能自己留意)。
- 模式匹配的编译实现(决策树等)完全没提。
- 结构体更新语法(..=)之类的表达式语法不在本章范围。
6. 可带走的
- let/函数参数/for 只许不可失败模式;match/if let/while let/let...else 允许可失败。
let Some(x) = opt else { ... }是 let 处使用可失败模式的唯一通道。|多模式、..=范围(仅数字/char)、字面量、解构(结构体/枚举/元组)。- 忽略:
_(不绑)、_x(绑、会 move)、..(忽略其余、每模式一次)。 - match guard:用外层变量、不做穷尽检查、对
|整体生效。 - @ 绑定:测模式的同时存值。
- 模式里的变量遮蔽外层;要比较外层值,用 guard。
7. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| let 即模式 | Chapter 19: Patterns and Matching | text/26-ch19-chapter-19-patterns-and-matching.txt:74(搜「PATTERN = EXPRESSION」) |
| if let 链与失穷尽 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:122(搜「Conditional if let」) · text/26-ch19-chapter-19-patterns-and-matching.txt:176(搜「check for exhaustiveness」) |
| while let | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:180(搜「while let Conditional Loops」) |
| for 与函数参数模式 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:208(搜「for Loops」) · text/26-ch19-chapter-19-patterns-and-matching.txt:234(搜「Function Parameters」) |
| refutability 与 E0005 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:268(搜「Refutability」) · text/26-ch19-chapter-19-patterns-and-matching.txt:303(搜「refutable pattern in local binding」) |
| let...else | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:326(搜「let Some(x) = some_option_value else」) |
| 字面量/多模式/范围 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:369(搜「Matching Literals」) · text/26-ch19-chapter-19-patterns-and-matching.txt:451(搜「Ranges of Values」) |
| 解构结构体 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:484(搜「Destructuring」) |
| 忽略值四姿势 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:677(搜「Ignoring Values」) · text/26-ch19-chapter-19-patterns-and-matching.txt:781(搜「subtle difference」) · text/26-ch19-chapter-19-patterns-and-matching.txt:814(搜「Remaining Parts」) |
| match guard | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:921(搜「match guard gives us」) · text/26-ch19-chapter-19-patterns-and-matching.txt:986(搜「precedence」) |
| @ 绑定 | 同上 | text/26-ch19-chapter-19-patterns-and-matching.txt:992(搜「at operator」) |
Footnotes
-
出处:「Chapter 19: Patterns and Matching」第 74 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:74,搜「PATTERN = EXPRESSION」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 176 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:176,搜「check for exhaustiveness」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 180 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:180,搜「while let Conditional Loops」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 208 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:208,搜「for Loops」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 303 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:303,搜「refutable pattern in local binding」)与第 326 段(text/26-ch19-chapter-19-patterns-and-matching.txt:326,搜「let Some(x) = some_option_value else」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 451 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:451,搜「Ranges of Values」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 484 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:484,搜「Destructuring」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 677 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:677,搜「Ignoring Values」)与第 781 段(text/26-ch19-chapter-19-patterns-and-matching.txt:781,搜「subtle difference」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 937 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:937,搜「if n == y」)。 ↩ ↩2 -
出处:「Chapter 19: Patterns and Matching」第 921 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:921,搜「match guard gives us」)与第 986 段(text/26-ch19-chapter-19-patterns-and-matching.txt:986,搜「precedence」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 992 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:992,搜「at operator」)。 ↩ -
出处:「Chapter 19: Patterns and Matching」第 283 段(
text/26-ch19-chapter-19-patterns-and-matching.txt:283,搜「shouldn’t have to worry」)。 ↩