Rust: 在一个分支中匹配两个枚举变体,使用 Option 绑定一个变体的字段?

huangapple go评论135阅读模式
英文:

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

问题

I'd like to match two variants of an enum in one match arm. There is one field that is "the same" in each, meaning that it has the same type, name, and semantic meaning. (field0: i32 in the example below.) I'd like to bind a local &mut i32 to field0 of the given variant. One variant also has a field that is not "shared" by the other. (field1: String in the example.) This I would like to bind to a local Option<&mut String>. Is there a neat way to do this?

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 });
}

This is the neatest alternative I know of so far:

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 => (),
    }
}
英文:

I'd like to match two variants of an enum in one match arm. There is one field that is "the same" in each, meaning that it has the same type, name and semantic meaning. (field0: i32 in the example below.) I'd like to bind a local &amp;mut i32 to field0 of the given variant. One variant also has a field that is not "shared" by the other. (field1: String in the example.) This I would like to bind to a local Option&lt;&amp;mut String&gt;. Is there a neat way to do this?

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

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

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

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

This is the neatest alternative I know of so far:

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

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

答案1

得分: 3

你可以使用 | 将两个变体的 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:?}");
英文:

You can make field0 of both variants into the same binding with |.

match value {
    Variant0 { field0, .. } | Variant1 { field0 } =&gt; println!(&quot;{field0}&quot;),
    _ =&gt; (),
}

However, your other requirement of field1 doesn't really fit into this syntax, so you need to do it manually. If you only needed an &amp; reference, you could do it in two match expressions, but that is unlikely to be any prettier.

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

huangapple
  • 本文由 发表于 2023年5月7日 03:02:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190619.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定