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 letlet/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
    }
}

 

阅读剩余
THE END