let 控制流
Rust 有几个与其他语言不同的控制流结构。它们用于模式匹配:
if let
表达式while let
expressionsmatch
表达式
if let
表达式
if let
表达式 能让你根据某个值是否与模式相匹配来执行不同的代码:
use std::time::Duration; fn sleep_for(secs: f32) { if let Ok(dur) = Duration::try_from_secs_f32(secs) { std::thread::sleep(dur); println!("slept for {:?}", dur); } } fn main() { sleep_for(-10.0); sleep_for(0.8); }
let else
expressions
如需了解匹配模式并从函数返回的常见情况,请使用 let else
。"else" 分支必须执行不同的结束方式(例如,return
、break
或 panic
,但不能直接执行到代码块的末尾)。
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let s = if let Some(s) = maybe_string { s } else { return Err(String::from("got None")); }; let first_byte_char = if let Some(first_byte_char) = s.chars().next() { first_byte_char } else { return Err(String::from("got empty string")); }; if let Some(digit) = first_byte_char.to_digit(16) { Ok(digit) } else { Err(String::from("not a hex digit")) } } fn main() { println!("result: {:?}", hex_or_die_trying(Some(String::from("foo")))); }
与 if let
一样,while let
变体会针对一个模式重复测试一个值:
fn main() { let mut name = String::from("Comprehensive Rust 🦀"); while let Some(c) = name.pop() { println!("character: {c}"); } // (There are more efficient ways to reverse a string!) }
Here String::pop
returns Some(c)
until the string is empty, after which it will return None
. The while let
lets us keep iterating through all items.
This slide should take about 10 minutes.
if-let
- Unlike
match
,if let
does not have to cover all branches. This can make it more concise thanmatch
. - 使用
Option
时,常见的做法是处理Some
值。 - 与
match
不同的是,if let
不支持模式匹配的 guard 子句。
let-else
if-let
s can pile up, as shown. The let-else
construct supports flattening this nested code. Rewrite the awkward version for students, so they can see the transformation.
重写后的版本为:
#![allow(unused)] fn main() { fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> { let Some(s) = maybe_string else { return Err(String::from("got None")); }; let Some(first_byte_char) = s.chars().next() else { return Err(String::from("got empty string")); }; let Some(digit) = first_byte_char.to_digit(16) else { return Err(String::from("not a hex digit")); }; return Ok(digit); } }
while-let
- 指出只要值与模式匹配,
while let
循环就会一直进行下去。 - You could rewrite the
while let
loop as an infinite loop with an if statement that breaks when there is no value to unwrap forname.pop()
. Thewhile let
provides syntactic sugar for the above scenario.