36、if let和let-else(模式匹配)
Concise branching(简洁的分支)
上一节练习的代码可以写成这个样子:
impl Ticket {
pub fn assigned_to(&self) -> &str {
match &self.status {
Status::InProgress { assigned_to } => assigned_to,
Status::Done | Status::ToDo => {
panic!(
"Only `In-Progress` tickets can be \
assigned to someone"
)
}
}
}
}
我们其实只关心Status::InProgress
这个变体。我们其实不需要匹配其他的所有变体。
新语法赶快给我端上来吧,哈哈哈。
if let
if let
结构允许我们只匹配枚举的单个变体,而无需处理所有其他的变体。
这是使用if let
简化assigned_to
的方式:
impl Ticket {
pub fn assigned_to(&self) -> &str {
if let Status::InProgress { assigned_to } = &self.status {
assigned_to
} else {
panic!(
"Only `In-Progress` tickets can be assigned to someone"
);
}
}
}
let/else
如果else
分支打算提前return(panic算做提前return)。我们可以使用let/else
构造:
impl Ticket {
pub fn assigned_to(&self) -> &str {
let Status::InProgress { assigned_to } = &self.status else {
panic!(
"Only `In-Progress` tickets can be assigned to someone"
);
};
assigned_to
}
}
它允许我们在不产生“右侧偏移(right drift)
”的情况下分配解构后的变量,即变量的分配与前面代码的缩进级别相同。
(想了半天,这个右侧偏移是什么鬼,原来是嵌套语句的缩进啊…)
Style(风格)
简单一句话,if let
和let/else
这俩东西很牛逼,用好了,是真的好。用烂了,是真的烂。
练习
题目:
pub enum Shape {
Circle { radius: f64 },
Square { border: f64 },
Rectangle { width: f64, height: f64 },
}
impl Shape {
// TODO: Implement the `radius` method using
// either an `if let` or a `let/else`.
pub fn radius(&self) -> f64 {
/* TODO */
}
}
题目啊。题目,还是描述的不清楚,你也没说要panic啊,说清楚点,除非你说这个就是必须要做的Rust编程界的惯例,必须遵守,那我就不蛐蛐你了。
答案:
use crate::Shape::Circle;
pub enum Shape {
Circle { radius: f64 },
Square { border: f64 },
Rectangle { width: f64, height: f64 },
}
impl Shape {
// TODO: Implement the `radius` method using
// either an `if let` or a `let/else`.
pub fn radius(&self) -> f64 {
let Circle { radius } = self else {panic!()};
*radius
}
}
阅读剩余
版权声明:
作者:CN059
链接:https://www.cn059.com/2025/09/16/36%e3%80%81if-let%e5%92%8clet-else%ef%bc%88%e6%a8%a1%e5%bc%8f%e5%8c%b9%e9%85%8d%ef%bc%89.html
文章版权归作者所有,未经允许请勿转载。
THE END