Rust 如何展平多个嵌套的模式匹配层?

Rust 如何展平多个嵌套的模式匹配层?,rust,enums,pattern-matching,flatten,Rust,Enums,Pattern Matching,Flatten,我的代码要求枚举在继续之前必须是某种类型(如果不是,那么这是一个不可恢复的错误)。用if let模式表达这一点会导致大量缩进和语法噪音。下面是一个例子: enum Fruit { Apple(i32), Banana(i32, i32), } enum Veggie { Tomato(bool), Pepper(i32), } fn test() -> i32 { let fruit = fruit_producing_func(); i

我的代码要求枚举在继续之前必须是某种类型(如果不是,那么这是一个不可恢复的错误)。用
if let
模式表达这一点会导致大量缩进和语法噪音。下面是一个例子:

enum Fruit {
    Apple(i32),
    Banana(i32, i32),
}

enum Veggie {
    Tomato(bool),
    Pepper(i32),
}

fn test() -> i32 {
    let fruit = fruit_producing_func();
    if let Fruit::Apple(x) = fruit {
        let veggie = veggie_producing_func(x);
        if let Veggie::Pepper(y) = veggie {
            y
        } else {
            panic!();
        }
    } else {
        panic!();
    }
}
在我的代码中,这种嵌套比两层要大得多。有没有更简洁的方式来表达这一点,从而避免创建额外的块,甚至重复
恐慌语句?简单地做:

let Fruit::Apple(x) = fruit;

导致错误,因为let绑定必须是详尽的(我希望它只会在匹配失败时死机)。

您可以在枚举本身上将检查重构为方便的方法,然后这将平坦化您的
测试功能:

枚举水果{
苹果(i32),
香蕉(i32,i32),
}
苹果{
//恐慌如果不是苹果
fn获得苹果公司(&self)->i32{
如果让水果::苹果(x)=自身{
*x
}否则{
恐慌!()
}
}
}
蔬菜{
番茄(bool),
胡椒粉(i32),
}
纯素{
//如果不是胡椒的话,那就是恐慌
fn获取胡椒粉(自我)->i32{
如果让素食者::胡椒粉(y)=自己{
*y
}否则{
恐慌!()
}
}
}
fn水果生产函数()->水果{
待办事项!()
}
fn素食生产函数(x:i32)->素食{
待办事项!()
}
fn test()->i32{
let fruit=水果生产函数();
让x=水果。得到苹果();
设veggie=veggie\u producting\u func(x);
让y=素食者。拿胡椒粉();
Y
}

您可以在枚举本身上将检查重构为方便的方法,然后这将平坦化您的
测试功能:

枚举水果{
苹果(i32),
香蕉(i32,i32),
}
苹果{
//恐慌如果不是苹果
fn获得苹果公司(&self)->i32{
如果让水果::苹果(x)=自身{
*x
}否则{
恐慌!()
}
}
}
蔬菜{
番茄(bool),
胡椒粉(i32),
}
纯素{
//如果不是胡椒的话,那就是恐慌
fn获取胡椒粉(自我)->i32{
如果让素食者::胡椒粉(y)=自己{
*y
}否则{
恐慌!()
}
}
}
fn水果生产函数()->水果{
待办事项!()
}
fn素食生产函数(x:i32)->素食{
待办事项!()
}
fn test()->i32{
let fruit=水果生产函数();
让x=水果。得到苹果();
设veggie=veggie\u producting\u func(x);
让y=素食者。拿胡椒粉();
Y
}

您可以使用“匹配”将其展平:

fn test() -> i32 {
    let fruit = fruit_producing_func();
    let x = match fruit {
        Fruit::Apple(x) => x,
        _ => panic!(),
    };
    let veggie = veggie_producing_func(x);
    let y = match veggie {
        Veggie::Pepper(y) => y,
        _ => panic!(),
    };
    y
}
或者,您可以在关联函数中实现匹配,然后使用常用的选项习惯用法处理该结果

impl Fruit {
    fn apple(&self) -> Option<i32> {
        if let Fruit::Apple(x) = self {
            Some(*x)
        } else {
            None
        }
    }
}

impl Veggie {
    fn pepper(&self) -> Option<i32> {
        if let Veggie::Pepper(y) = self {
            Some(*y)
        } else {
            None
        }
    }
}
fn test() -> i32 {
    let fruit = fruit_producing_func();
    let x =  fruit.apple().unwrap();
    let veggie = veggie_producing_func(x);
    veggie.pepper().expect("Tomato is a fruit after all")
}
impl水果{
fn苹果公司(和自助)->选项{
如果让水果::苹果(x)=自身{
一些(*x)
}否则{
没有一个
}
}
}
纯素{
fn pepper(&self)->选项{
如果让素食者::胡椒粉(y)=自己{
一些(*y)
}否则{
没有一个
}
}
}
fn test()->i32{
let fruit=水果生产函数();
设x=水果。苹果()。展开();
设veggie=veggie\u producting\u func(x);
expect(番茄毕竟是一种水果)
}

您可以使用“匹配”来将其展平:

fn test() -> i32 {
    let fruit = fruit_producing_func();
    let x = match fruit {
        Fruit::Apple(x) => x,
        _ => panic!(),
    };
    let veggie = veggie_producing_func(x);
    let y = match veggie {
        Veggie::Pepper(y) => y,
        _ => panic!(),
    };
    y
}
或者,您可以在关联函数中实现匹配,然后使用常用的选项习惯用法处理该结果

impl Fruit {
    fn apple(&self) -> Option<i32> {
        if let Fruit::Apple(x) = self {
            Some(*x)
        } else {
            None
        }
    }
}

impl Veggie {
    fn pepper(&self) -> Option<i32> {
        if let Veggie::Pepper(y) = self {
            Some(*y)
        } else {
            None
        }
    }
}
fn test() -> i32 {
    let fruit = fruit_producing_func();
    let x =  fruit.apple().unwrap();
    let veggie = veggie_producing_func(x);
    veggie.pepper().expect("Tomato is a fruit after all")
}
impl水果{
fn苹果公司(和自助)->选项{
如果让水果::苹果(x)=自身{
一些(*x)
}否则{
没有一个
}
}
}
纯素{
fn pepper(&self)->选项{
如果让素食者::胡椒粉(y)=自己{
一些(*y)
}否则{
没有一个
}
}
}
fn test()->i32{
let fruit=水果生产函数();
设x=水果。苹果()。展开();
设veggie=veggie\u producting\u func(x);
expect(番茄毕竟是一种水果)
}