表达式与控制流 — 分号是有意义的¶
这一章讲一件事: Rust 看着像 C,其实「if 有值、循环有值、块有值」—— 它是一门表达式语言。这个底色一变,分号、大括号、else 这些熟面孔全部有了新含义。 章首的题辞是 Alan Perlis 的毒舌:「Lisp 程序员知道一切东西的值,却不知道任何东西的代价。」1
1. 顶层全景:表达式做所有工作¶
C 的世界:表达式(有值)与语句(没值)分得很清;if/for 是语句,不能嵌进表达式
│
▼
Rust 的世界:几乎所有东西都是表达式,都能放在「需要一个值」的地方
│
├─ 块 { … } = 值是最后一个表达式的值;分号 = 丢弃值、变回 ()
├─ if / match = 值(分支必须同类型、必须穷尽)
├─ 循环 = 值(loop 配 break 带值)
└─ 发散(! 类型)的表达式免于类型一致检查
图说:语法层的统一换来的是「少几种特殊构造」——没有三元运算符、没有 ++/--。
运算符优先级速查(从高到低)¶
表 5-1 的骨架,按优先级从高到低排列;同组同优先级,从左往右结合38:
| 组 | 运算符 | 备注 |
|---|---|---|
| 最高 | 路径 ::、方法调用 .、函数调用 ()、下标 []、宏 ! |
字段访问 .x、元组字段 .0 也在这一层 |
| 一元 | ! − * & &mut |
逻辑非、负号、解引用、借 |
| as | as |
类型转换,可与其他算术连用(左结合) |
| 乘除余 | * / % |
整数除法向零取整 |
| 加减 | + − |
|
| 移位 | << >> |
|
| 位与 | & |
注意:比比较运算高,这是和 C 的不同 |
| 位异或、位或 | ^ | |
|
| 比较 | == != < <= > >= |
不可链式连用 |
| 逻辑与、或 | && || |
短路,操作数必须 bool |
| 区间 | .. ..= |
不可链式连用 |
| 赋值 | = += -= … |
右结合,不可链式连用 |
容易踩的三处:方法调用优先级高于一元负号(上一章 -4.abs() 的坑);
位运算优先级高于比较(写位测试不用加括号);比较和赋值都不能连写
(a < b < c 和 a = b = c 都是语法错误)39。
2. 表达式语言:没有三元运算符的真正原因¶
C 里 5 * (fahr-32) / 9 是表达式、for (...) { ... } 是语句,界线分明。
Rust 里这条线几乎消失:if 和 match 产生值2。第一章那个上色语句就是个 match 表达式:
pixels[r * bounds.0 + c] = match escape_time(point, 255) {
None => 0,
Some(count) => 255 - count as u8,
};
if 也能初始化变量、match 能当函数参数传3。于是 C 的三元运算符 c ? a : b 在 Rust 里多余——
if 表达式两个分支都办事,「三元运算」只是它的一个特例4。
本章的主线例子就用这个上色语句往下走:match 的值 → 块当分支 → 分号的作用,一级级拆开。
3. 块与分号:值去哪了¶
块是最通用的表达式:产生一个值,可以用在任何需要值的地方5。 块的值 = 块里最后一个不带分号的表达式的值。分号干什么?把一个表达式变成语句,值被丢弃。
let msg = {
let dandelion_control = puffball.open(); // let:分号必填
dandelion_control.release_all_seeds(codes); // 有分号:调了,返回值丢弃
dandelion_control.get_status() // 无分号:这个值就是块的值
};
(这是原书的原例,变量名保持原样:一块地里三个动作,前两个只要副作用,最后一个要结果。)
由此解释一个著名的新手报错。漏写分号:
C 会提示「缺分号」;Rust 报:mismatched types: expected (), found (u32, u32)——
没有分号,块的值就变成了 compute_size() 的返回值(一对 u32),而 if 没有 else 时分支类型必须是 ()。
好在编译器认得这个病,直接建议「try adding a semicolon」6。
带标签的块:块可以起名('trim: { … }),break 'trim 值 提前退出整个块并交出值——
类似函数里的 return,适合一串「先做副作用、再定结果」的步骤7。
4. 声明:let、遮蔽、嵌套函数¶
let 声明局部变量,类型和初始值都可省,分号必填;可以先声明后赋值——
只要每条路径上恰好初始化一次,连 mut 都不用加8。
遮蔽(shadowing):同一个名字再 let 一次,是第二个变量——新类型、新值,盖掉旧的:
遮蔽在 Rust 代码里非常常见;它防的错是:名字现在指新值了,后面的代码想误用旧值都用不了9。
书里自己约定:教学时给第一个变量加 _result 后缀以示区分(如 line_result)10。
嵌套 item:块里还能声明函数、结构体、甚至整个模块。但嵌套 fn 看不见外层变量——
要捕获环境,得用闭包(后面章节)11。
带标签块的完整例子¶
书上的完整例子是一个「判断换行符类型」的小函数片段,标签 'trim 让它读起来像一组带早退的步骤25:
let trimmed = 'trim: {
if string.chars().last() != Some('\n') {
break 'trim None; // 不是换行结尾:退出整块,值是 None
}
string.pop();
if string.chars().last() != Some('\r') {
break 'trim Some(Newline::Unix); // 只吃掉了 \n:Unix 换行
}
string.pop();
Some(Newline::Windows) // \r\n 都吃掉:Windows 换行
};
三个出口,两个带值退出,一个正常落底——等价的 if-else 链会深三层。 作者提醒:这个写法适合「一串有副作用的步骤、每步都可能定结果」,滥用会不如普通分支好读26。
变量命名的宽松度¶
顺带一个轻松的事实:Rust 对标识符的「字母」定义极宽——希腊字母、带重音的拉丁字符都行, 只要 Unicode 标准认为它能当字母;emoji 不行。变量名须以字母或下划线开头,后面才能跟数字27。
5. if、match、if let、let-else¶
if:条件必须 bool;括号可省(写了还警告),大括号必填;无 else 等价于空 else12。
match:像 C 的 switch,灵活得多。形态是 match value { pattern => expr, … }:
按顺序匹配,命中即算完;至少一个分支必须命中——Rust 禁止不覆盖全部情况的 match13:
let score = match card.rank {
Jack => 10,
Queen => 10,
Ace => 11,
}; // 错误:nonexhaustive patterns(没处理数字牌)
原书还交代了编译器怎么优化:分支是常量就查跳转表;每个分支产出常量值就建数组按值索引——
除了边界检查没有任何分支,和 C++ 的 switch 同款待遇14。
分支类型必须一致;if 也一样,if c { 1 } else { 0 } 可以,if c { "a" } else { 9 } 不行,
if c { "a" } 不行(没有 else 时,条件为假的结果是 (),和 "a" 对不上)15。
模式的全家桶(区间、解构、借用)留给后面章节,这里记住 _ 通配、必须穷尽、模式在前分支在后。
if let:一个模式的 match 的简写。if let Some(cookie) = request.session_cookie { … }
匹配成功走块、失败走 else;从来不是必需品(match 都能写),但省一层缩进16。
let-else:let 模式 = 表达式 else { 发散块 };——匹配不上就走发散块(必须发散:
panic/return/无限循环),匹配上才继续往下17。经典场景:配置文件打不开就退出:
let Ok(config_file) = File::open(&config_path) else {
panic!("Unable to open config file {}.", config_path.display());
};
let config = parse_config(config_file); // 走到这里,config_file 一定是 Ok 里的值
块里还能装什么:item 声明¶
块不只装语句,还能装声明——任何能出现在全局的声明都能塞进块里:fn、struct、
use,甚至一整个模块。函数里套函数是完全合法的33:
fn show_files() -> io::Result<()> {
let mut v = vec![];
// ……
fn cmp_by_timestamp_then_name(a: &FileInfo, b: &FileInfo) -> Ordering {
a.timestamp.cmp(&b.timestamp).reverse() // 新的在前
.then(a.path.cmp(&b.path)) // 同名再比路径
}
v.sort_by(cmp_by_timestamp_then_name);
// ……
}
有一条军规:嵌套的 fn 看不见外层的局部变量。cmp_by_timestamp_then_name 想用 v? 不行。要捕获环境,得用闭包(专章再讲)。作用域倒是覆盖整个块——声明在块的任何位置, 整块都可见,因为 fn 这类 item 在编译期就处理完了34。
为什么语言要留这个「正交性」?原书说了句实话:程序员(尤其写宏的程序员) 总会找到语言每一分正交性的用途35。
return 与 ?:能放弃手头的工作¶
return 看着平凡,在表达式语言里它有一个精确的角色:放弃正在求值的表达式,
直接从函数返回。第 1 章那个 ? 操作符展开后就是个带 return 的 match36:
let output = match File::create(filename) {
Ok(f) => f, // 成功:整个 match 的值是 f,继续往下
Err(err) => return Err(err), // 失败:不管正在给谁赋值,立刻带错出函数
};
注意失败分支的语义:此刻我们正在计算 let output = … 的右边,
return 一出现,这个未完成的赋值整个作废。这就是「发散表达式豁免于类型一致」的第一用途——
return Err(err) 的类型是 !,所以它出现在「值必须是 File」的上下文里也不冲突37。
match 的三条军规¶
把分散在例子里的规定收拢成军规40:
- 顺序就是优先级。模式从上到下依次试,命中即停;把宽泛的模式写在前面, 后面的分支就成了死代码——编译器会警告你。
- 通配符
_必须殿后。它兜住一切,放在前面会把后面的分支全毙掉(编译器同样警告)。 - 分支必须覆盖所有可能值——非穷尽(
nonexhaustive patterns)是编译错误,不是警告。
三条的共同内核:match 不给你「漏掉情况」的机会。C 的 switch 漏了 default 只是风格问题, Rust 把它升格成类型检查——这正是「表达式语言」追求的一致性: 有值的东西,值的来历必须完整41。
6. 循环:四种形态与一个刻意的盲区¶
| 形态 | 说明 |
|---|---|
while 条件 { … } |
同 C,条件必须 bool |
while let 模式 = 表达式 { … } |
每轮开头匹配:匹配上就跑,匹配不上就退出 |
loop { … } |
无限循环,靠 break/return 出 |
for 模式 in 可迭代 { … } |
遍历;C 的三段式 for 换成区间:for i in 0..20(末个打印 19) |
循环也是表达式,但 while/for 的值恒为 ();loop 可以带值:break 值 就是循环表达式的值18。
for 循环遵守移动语义:for s in strings 把向量消耗掉(元素逐个搬进 s);
for s in &strings 只借;for s in &mut strings 借可变、拿到 &mut String19。
break/continue:break 退出循环;带标签('search:)能退出外层循环;
break 'outer i 标签和值可以同带。continue 跳下一轮20。
为什么 Rust 要有 loop? 这是原书给的设计内幕,值得单独记。编译器有几项流敏感分析: 每条路径是否都返回了正确类型、变量是否可能没初始化就被用、有没有不可达代码。 做这类分析要在「简单」和「聪明」之间选边:聪明的版本少误报,但程序员更难懂编译器在说什么。 Rust 选了简单:分析不看循环条件,假设任何条件都可能真也可能假。21
后果:这个完全安全的函数会被拒——
fn wait_for_process(process: &mut Process) -> i32 {
while true {
if process.wait() {
return process.exit_code();
}
}
} // 错误:expected i32, found ()——分析器不敢确定 while true 是死循环
loop 就是「说你想说的」的解法:它声明了「这就是个死循环」,类型检查满意放行22。
while let:每轮重新匹配¶
while let 是 if let 的循环版:每轮开头匹配一次,匹配上就跑,匹配不上就退出28。
for 与区间:C 循环的真正替身¶
C 的 for (int i = 0; i < 20; i++) 在 Rust 里是 for i in 0..20——最后打印 19。
0..20 不是个语法糖般的特殊东西,它是一个结构体值(std::ops::Range { start: 0, end: 20 }),
能拿去 for 循环是因为标准库给它实现了迭代接口;数组、切片、标准集合同理29。
for 循环与移动语义的三档用法(第 3 章的实战版):
| 写法 | s 的类型 | strings 的下场 |
|---|---|---|
for s in strings |
String |
被消耗,循环后不可用 |
for s in &strings |
&String |
只借,完好 |
for s in &mut strings |
&mut String |
借可变,可改每个元素 |
想循环后还用集合,就迭代引用;想连容器一起处理掉,就迭代本体30。
break 带值:loop 的返回值¶
loop 的真身是「能产生值的表达式」,值从 break 交出来:
let answer = loop {
if let Some(line) = next_line() {
if line.starts_with("answer: ") {
break line; // 找到就带值退出
}
} else {
break "answer: nothing"; // 读到文件尾也退出
}
};
规则:loop 里所有 break 带的值类型必须一致,那就是 loop 的类型;
for/while 的 break 不许带值(它们的类型恒为 ())31。continue 照常跳下一轮,
也能带标签,跳到外层循环的下一轮32。
7. 发散与 ! 类型¶
有些表达式不照常结束:break/return 中途退场、loop 无 break 永不结束、panic!/process::exit 直接终止。
它们没有普通类型,被赋予特殊类型 !(发音「never」),并且豁免于「类型必须一致」——
所以 if c { "a" } else { return } 合法:else 分支是 !,什么类型都接得住23。
fn exit(code: i32) -> ! 的签名读作:永不返回。自己也能写发散函数(比如 serve_forever)24。
8. 作者的判断与证据¶
- 「Rust 选了简单」(流敏感分析不查循环条件)是明示的设计决策,代价是误拒少数安全程序
(
while true那例),收益是程序员能预测编译器的行为——判断标准写得很清楚21。 - 「match 的常量分支编译成数组索引」是编译器实现细节,但属于可验证的既有行为14。
- 「分号 = 丢弃值」是语义定义,不是风格问题——由此解释了报错信息的长相6。
9. 边界与局限¶
- 模式匹配的完整能力(结构解构、守卫、绑定模式)本章只有预告,系统性讲解在未放出的章节;
?与 return 的配合只点到为止,错误处理的完整形态(error conversion 等)缺失;- 闭包被推迟——表达式层因此少了「函数即值」的一角。
10. 可带走的¶
主线例子一行版: match escape_time(point, 255) { None => 0, Some(c) => 255 - c } 当表达式赋给像素 →
分支可以是大块(块的值 = 最后无分号表达式的值)→ 分号丢弃值 → if/match 的值类型必须处处一致。
- Rust 是表达式语言:表达式做所有工作,if/match/块/循环都有值;
- 没有三元运算符,因为 if 表达式已经覆盖;
- 块的值 = 最后一个不带分号的表达式;分号 = 「调用、丢弃值」;
- 漏分号的报错是 mismatched types(不是缺分号)——因为块的类型变了;
- 同名再 let 是遮蔽:新变量盖旧变量,防止误用旧值;
- match 必须穷尽;分支同类型;if 无 else 时分支必须是
(); - if let / let-else 是一个模式 match 的简写;let-else 的 else 必须发散;
- for 遵守移动语义:遍历值消耗它,遍历 &值只借;
- loop 存在的原因:类型检查的流敏感分析故意保持简单,不认 while true;
!类型 = 永不结束;豁免于类型一致检查。
11. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 表达式语言定位 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:36(搜「expression language」) |
| 无三元运算符 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:63(搜「ternary operator」) |
| 块是最通用的表达式 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:253(搜「most general」) |
| 分号 = 丢弃值 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:274(搜「dropped」) |
| 漏分号的报错 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:292(搜「mismatched types」) |
| 带标签的块 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:303(搜「labeled with a lifetime」) |
| 遮蔽 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:348(搜「shadowing」) |
| 嵌套 fn 不见外层 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:378(搜「cannot access」) |
| match 必须穷尽 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:431(搜「cover all possible values」) · text/15-ch05-chapter-5-expressions.txt:437(搜「nonexhaustive」) |
| 分支类型一致 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:439(搜「same type」) |
| 跳转表/数组优化 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:411(搜「jump table」) |
| if let 是简写 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:485(搜「never strictly necessary」) |
| let-else 与发散块 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:494(搜「only one acceptable pattern」) · text/15-ch05-chapter-5-expressions.txt:507(搜「diverging」) |
| 循环四种形态 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:516(搜「four looping」) |
| for 的移动语义 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:558(搜「consumes the value」) |
| break 带标签带值 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:621(搜「labeled」) · text/15-ch05-chapter-5-expressions.txt:637(搜「outer」) |
| 流敏感分析选简单 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:695(搜「went for simplicity」) |
| loop 是「说你想说的」 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:709(搜「say-what-you-mean」) |
| 带标签块与 Unicode 命名 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:303(搜「'trim」) |
| for 的三档迭代 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:558(搜「consumes the value」) |
| break 带值的 loop | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:593(搜「answer: nothing」) |
| 嵌套函数与 item 声明 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:357(搜「item」) |
| return 与 ? 的展开 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:666(搜「abandon」) |
| 运算符优先级速查 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:67(搜「precedence」) |
| match 三条军规 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:409(搜「precedence」) |
| ! 类型 | Chapter 5. Expressions | text/15-ch05-chapter-5-expressions.txt:713(搜「special type」) · text/15-ch05-chapter-5-expressions.txt:717(搜「divergent function」) |
-
出处:「Chapter 5. Expressions」第 13–15 段(
text/15-ch05-chapter-5-expressions.txt:13-15,搜「cost of nothing」)。Alan Perlis 的警句第 55 条。 ↩ -
出处:「Chapter 5. Expressions」第 36–38 段(
text/15-ch05-chapter-5-expressions.txt:36-38,搜「expression language」)。 ↩ -
出处:「Chapter 5. Expressions」第 46–61 段(
text/15-ch05-chapter-5-expressions.txt:46-61,搜「initialize a variable」)。 ↩ -
出处:「Chapter 5. Expressions」第 63 段(
text/15-ch05-chapter-5-expressions.txt:63,搜「ternary operator」)。 ↩ -
出处:「Chapter 5. Expressions」第 253 段(
text/15-ch05-chapter-5-expressions.txt:253,搜「most general」)。 ↩ -
出处:「Chapter 5. Expressions」第 282–301 段(
text/15-ch05-chapter-5-expressions.txt:282-301,搜「mismatched types」)。 ↩↩ -
出处:「Chapter 5. Expressions」第 303–317 段(
text/15-ch05-chapter-5-expressions.txt:303-317,搜「labeled with a lifetime」)。 ↩ -
出处:「Chapter 5. Expressions」第 327–339 段(
text/15-ch05-chapter-5-expressions.txt:327-339,搜「initialized with a later assignment」)。 ↩ -
出处:「Chapter 5. Expressions」第 348 段(
text/15-ch05-chapter-5-expressions.txt:348,搜「shadowing」)。 ↩ -
出处:「Chapter 5. Expressions」第 355 段(
text/15-ch05-chapter-5-expressions.txt:355,搜「_result suffix」)。 ↩ -
出处:「Chapter 5. Expressions」第 357–378 段(
text/15-ch05-chapter-5-expressions.txt:357-378,搜「cannot access」)。 ↩ -
出处:「Chapter 5. Expressions」第 384–398 段(
text/15-ch05-chapter-5-expressions.txt:384-398,搜「curly braces」)。 ↩ -
出处:「Chapter 5. Expressions」第 422–437 段(
text/15-ch05-chapter-5-expressions.txt:422-437,搜「cover all possible values」)。 ↩ -
出处:「Chapter 5. Expressions」第 411 段(
text/15-ch05-chapter-5-expressions.txt:411,搜「jump table」)。 ↩↩ -
出处:「Chapter 5. Expressions」第 439–450 段(
text/15-ch05-chapter-5-expressions.txt:439-450,搜「same type」)。 ↩ -
出处:「Chapter 5. Expressions」第 464–490 段(
text/15-ch05-chapter-5-expressions.txt:464-490,搜「never strictly necessary」)。 ↩ -
出处:「Chapter 5. Expressions」第 494–512 段(
text/15-ch05-chapter-5-expressions.txt:494-512,搜「only one acceptable pattern」)。 ↩ -
出处:「Chapter 5. Expressions」第 534 段(
text/15-ch05-chapter-5-expressions.txt:534,搜「Loops are expressions」)。 ↩ -
出处:「Chapter 5. Expressions」第 556–580 段(
text/15-ch05-chapter-5-expressions.txt:556-580,搜「consumes the value」)。 ↩ -
出处:「Chapter 5. Expressions」第 584–651 段(
text/15-ch05-chapter-5-expressions.txt:584-651,搜「break」)。 ↩ -
出处:「Chapter 5. Expressions」第 683–695 段(
text/15-ch05-chapter-5-expressions.txt:683-695,搜「went for simplicity」)。 ↩↩ -
出处:「Chapter 5. Expressions」第 697–709 段(
text/15-ch05-chapter-5-expressions.txt:697-709,搜「bogus」)。 ↩ -
出处:「Chapter 5. Expressions」第 711–717 段(
text/15-ch05-chapter-5-expressions.txt:711-717,搜「special type」)。 ↩ -
出处:「Chapter 5. Expressions」第 717–727 段(
text/15-ch05-chapter-5-expressions.txt:717-727,搜「divergent function」)。 ↩ -
出处:「Chapter 5. Expressions」第 303–317 段(
text/15-ch05-chapter-5-expressions.txt:303-317,搜「'trim」)。 ↩ -
出处:「Chapter 5. Expressions」第 317 段(
text/15-ch05-chapter-5-expressions.txt:317,搜「more readable」)。 ↩ -
出处:「Chapter 5. Expressions」第 325 段(
text/15-ch05-chapter-5-expressions.txt:325,搜「Unicode Standard Annex」)。 ↩ -
出处:「Chapter 5. Expressions」第 538 段(
text/15-ch05-chapter-5-expressions.txt:538,搜「analogous」)。 ↩ -
出处:「Chapter 5. Expressions」第 542–556 段(
text/15-ch05-chapter-5-expressions.txt:542-556,搜「IntoIterator」)。 ↩ -
出处:「Chapter 5. Expressions」第 558–580 段(
text/15-ch05-chapter-5-expressions.txt:558-580,搜「consumes the value」)。 ↩ -
出处:「Chapter 5. Expressions」第 588–604 段(
text/15-ch05-chapter-5-expressions.txt:588-604,搜「answer: nothing」)。 ↩ -
出处:「Chapter 5. Expressions」第 606–651 段(
text/15-ch05-chapter-5-expressions.txt:606-651,搜「labeled」)。 ↩ -
出处:「Chapter 5. Expressions」第 357–378 段(
text/15-ch05-chapter-5-expressions.txt:357-378,搜「item」)。 ↩ -
出处:「Chapter 5. Expressions」第 378 段(
text/15-ch05-chapter-5-expressions.txt:378,搜「cannot access」)。 ↩ -
出处:「Chapter 5. Expressions」第 380 段(
text/15-ch05-chapter-5-expressions.txt:380,搜「orthogonality」)。 ↩ -
出处:「Chapter 5. Expressions」第 666–679 段(
text/15-ch05-chapter-5-expressions.txt:666-679,搜「abandon」)。 ↩ -
出处:「Chapter 5. Expressions」第 711–717 段(
text/15-ch05-chapter-5-expressions.txt:711-717,搜「exempt」)。 ↩ -
出处:「Chapter 5. Expressions」第 67–249 段(
text/15-ch05-chapter-5-expressions.txt:67-249,搜「precedence」)。分组依据表 5-1,结合性说明见第 245–249 段(搜「left-associative」)。 ↩ -
出处:「Chapter 5. Expressions」第 249 段(
text/15-ch05-chapter-5-expressions.txt:249,搜「can't be chained」)。 ↩ -
出处:「Chapter 5. Expressions」第 400–431 段(
text/15-ch05-chapter-5-expressions.txt:400-431,搜「wildcard」)。 ↩ -
出处:「Chapter 5. Expressions」第 431–437 段(
text/15-ch05-chapter-5-expressions.txt:431-437,搜「prohibits」)。 ↩