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.