在一个臂中匹配两个枚举变体,使用 Option?

Match two enum variants in one arm, binding field of one variant using Option?

提问人:Simplex 提问时间:5/7/2023 最后编辑:cafce25Simplex 更新时间:11/8/2023 访问量:328

问:

我想在一个匹配臂中匹配枚举的两个变体。每个字段中都有一个“相同”的字段,这意味着它具有相同的类型、名称和语义含义。(在下面的示例中。我想将给定变体的本地绑定到。一个变体还具有一个未被另一个变体“共享”的字段。(在示例中。我想绑定到本地.有没有一种巧妙的方法可以做到这一点?field0: i32&mut i32field0field1: StringOption<&mut String>

enum Enum {
    Variant0 { field0: i32, field1: String },
    Variant1 { field0: i32 },
    Variant2,
}

fn mutate(value: &mut Enum) {
    match value {
        // Hopefully some pattern matching magic
        // to get a local &mut i32 and a local
        // Option<&mut String>.
    }
}

fn main() {
    mutate(&mut Enum::Variant0 {
        field0: 123,
        field1: "hello".to_string(),
    });

    mutate(&mut Enum::Variant1 { field0: 456 });
}

这是迄今为止我所知道的最简洁的替代方案:

fn mutate(value: &mut Enum) {
    match value {
        Enum::Variant0 { field0, .. } | Enum::Variant1 { field0 } => {
            // Mutate *field0 here.

            if let Enum::Variant0 { field1, .. } = value {
                // Mutate *field1 here.
            }
        }
        Enum::Variant2 => (),
    }
}
Rust 枚举 模式匹配

评论

1赞 cafce25 11/8/2023
您最新的编辑添加了一个答案,您应该将其添加为答案!

答:

3赞 drewtato 5/7/2023 #1

您可以使用 将这两个变体合并为相同的绑定。field0|

match value {
    Variant0 { field0, .. } | Variant1 { field0 } => println!("{field0}"),
    _ => (),
}

但是,您的其他要求并不适合此语法,因此您需要手动完成。如果你只需要一个引用,你可以用两个匹配表达式来做,但这不太可能更漂亮。field1&

let (field0, field1) = match value {
    Variant0 { field0, field1 } => (field0, Some(field1)),
    Variant1 { field0 } => (field0, None),
    Variant2 => return,
};
println!("{field0}, {field1:?}");

评论

0赞 Simplex 5/7/2023
我根据您的第一个建议在原始帖子中添加了一个替代方案,使用额外的 .实际上,它看起来非常整洁!我可能会同意。if let
0赞 cafce25 #2

Simplex 问题的解决方案:

这是迄今为止我所知道的最简洁的替代方案:

fn mutate(value: &mut Enum) {
    match value {
        Enum::Variant0 { field0, .. } | Enum::Variant1 { field0 } => {
            // Mutate *field0 here.

            if let Enum::Variant0 { field1, .. } = value {
                // Mutate *field1 here.
            }
        }
        Enum::Variant2 => (),
    }
}