2.3 函数与控制流:庭审流程


2.3 函数与控制流:庭审流程

本节摘要:讲清 Rust"表达式优先"的语言性格——赋值语句之外的多数语法块都产生值;演示 if 作表达式、loop 的 break 返回值、match 的穷尽性检查。读完你能写出无多余中间变量的紧凑流程代码。

函数:参数与返回值都要亮明身份

fn fine(amount: u32, reason: &str) -> u32 { println!("罚款 {},案由:{}", amount, reason); amount * 2 // 无分号:这是返回表达式 }

最后一行不带分号即为返回值;带分号就变成语句,返回值退化为单元值——新手高频案件" expected u32, found()" 多半是这枚分号。提前返回用 return。

表达式判决:if 也能当右值

let severity = if loss > 1000 { "重大" } else { "一般" };

if 的两个分支必须同类型,编译器把这个一致性也管起来。三元运算符因此不存在——if 表达式已覆盖。

三种循环各有判决书:

let mut n = 0; let result = loop { // loop 的 break 可以带值返回 n += 1; if n == 10 { break n * 2; } }; for i in 1..=5 { print!("{} ", i); } // 含终值区间 for b in [1, 2, 3] { print!("{} ", b); } // 遍历数组,越界不可能

loop 配 break 带值,配合循环标签可从嵌套深处直接结案:'outer: loop { ... break 'outer x; }

match:穷尽性是硬法条

enum Verdict { Guilty, Innocent, Mistrial } fn penalty(v: Verdict) -> u32 { match v { Verdict::Guilty => 100, Verdict::Innocent => 0, Verdict::Mistrial => 30, } }

少写一个分支,编译器报 non-exhaustive patterns,并贴心列出漏掉的变体。这与 C 的 switch(漏 case 静默通过)是制度级差异——枚举第 4 章展开,这里先记住:match 必须接住每一种可能_ 是兜底通配。

图:控制流语句对比

图:控制流语句对比

要点回顾

  • 分号把表达式变成语句,函数末行多分号是高频案件;
  • if 是表达式,可直接赋值,分支类型必须一致;
  • loop 的 break 可携带返回值,循环标签处理嵌套;
  • match 穷尽性受编译器强制,漏分支编不过。

loop 是表达式:break 可以携带判词

Rust 的控制流几乎都是表达式,loop 也不例外——这使它天然适合"重试直到成功"的模式,且不需要外部可变标志位。

fn next_case_id(counter: &mut u32) -> u32 { loop { *counter += 1; if *counter % 7 != 0 { // 跳过不吉利编号只是业务规则的替身 break *counter; // break 带值:loop 的产出 } } } fn main() { let mut c = 6; let id = next_case_id(&mut c); // 得 8:7 被跳过 println!("受理编号 {}", id); }

同一家族还有 while let 与 if let,两者都是 match 的单项速裁版。选择的原则很简单:只有一种关心的形态用 if let,两种以上或需要穷尽性保证时上 match——match 的穷尽检查是编译器免费送的审查员,漏掉的形态会在编译期点名。

标签:多层循环的精确退庭

嵌套循环里 break 默认只退出一层,处理二维检索这类案件容易退错层。标签把退出目标写成显式名字。

fn find_pair(grid: &[[u8; 3]; 3], target: u8) -> (usize, usize) { let mut found = (0, 0); 'outer: for (r, row) in grid.iter().enumerate() { for (c, cell) in row.iter().enumerate() { if *cell == target { found = (r, c); break 'outer; // 一次退到外层,不再扫余下各行 } } } found }

对比"用标志变量逐层判断退出"的传统写法,标签少两个可变状态,控制流意图也更直白。continue 同样可以带标签跳到指定层下一轮。

控制流手段的选型表

手段 本质 何时选用
if / else 表达式判分支 二三路、条件彼此独立
match 穷尽模式分派 枚举形态、范围与守卫
if let / while let 单形态速裁 只关心一种可能
loop / while 循环,loop 可带值产出 重试、状态机推进
? 运算符 错误短路上抛 第 6 章专庭审理

返回值风格也顺带立个规矩:能用表达式收尾的函数(最后一句就是值)不必写 return,return 只用于提前退庭。全文统一这一条,代码的呼吸感会明显一致。

穷尽性错误的现场与修法

enum Filing { Open, Closed(u32) } fn status(f: &Filing) -> &'static str { match f { Filing::Open => "进行中", // 漏掉 Closed:E0004 non-exhaustive patterns } .to_string() .leak() // 占位,勿学 }

上面示例故意保留两处问题:E0004 的修复是补全分支而非加 _(枚举新增形态时 _ 会静默吞掉新形态);leak 写法是坏味道示范,返回 String 才是正解。match 的价值恰恰在编译器替你追形态:枚举演进时,所有漏改的 match 会同时点名,这是重构安全网的重要一环。

三段式改写练习

把同一段"找最大值"逻辑分别用 loop+break、while+索引、迭代器 max_by 三种写法各写一遍,对比行数与可变状态数量。典型结论:loop 版两个可变变量,while 版一个外加边界判断,迭代器版零可变状态。这个练习建立的手感是后续章节反复引用的——第 4 章集合与第 6 章 Result 组合子,都是"用表达式与组合子消灭可变状态"这条主线的延续。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U