简体   繁体   中英

How to match an enum variant in a match

Is there a position for @ operator or some other solution that would bind the variable in a match arm to a variant type rather than to the entire enum? In the following example, all bar , baz and qux have types of Foo, rather than Foo::Bar, Foo::Baz, Foo::Qux and the sample fails to compile.

enum Foo {
   Bar(i32),
   Baz{s: String},
   Qux,
}

fn main() {
  let foo = Foo::Bar(42);

  match foo {
    bar @ Bar(..) => bar.0.to_string(),
    baz @ Baz{..} => baz.s,
    qux @ Qux => "".to_owned(),
  }
}

I think the syntax you're looking for is this?

enum Foo {
   Bar(i32),
   Baz{s: String},
   Qux,
}

fn main() {
  let foo = Foo::Bar(42);

  let s = match foo {
    Foo::Bar(bar) => bar.to_string(),
    Foo::Baz{s} => s,
    Foo::Qux => "".to_owned(),
  };
  
  dbg!(s);
}

What you're looking for is use :

enum Foo {
   Bar(i32),
   Baz{s: String},
   Qux,
}

fn main() {
  use Foo::*;
  let foo = Bar(42);

  let s = match foo {
    Bar(bar) => bar.to_string(),
    Baz{s} => s,
    Qux => "".to_owned(),
  };
}

Though handy if they existed, there is no such thing as an enum variant type in Rust. All variants have the same type. Their contents, on the other hand, might carry values of different types.

For example, both Foo::Bar(1) and Foo::Qux have the same type , which is Foo . So you can't bind those values and treat them differently as they are of the same type.

The most “idiomatic” solution I can think of is to just grab what's inside of the specific enum variant you're currently matching on, like so:

fn main() {
  let foo = Foo::Bar(42);

  let my_string = match foo {
    Bar(bar) => bar.to_string(),
    Baz{ s } => s,
    Qux => "".to_owned(),
  };
}

To reuse a variant enum you need to use enum tuple style and define external structure, it's a lot more used than enum struct:

struct Bar(i32);
struct Baz {
    s: String,
}

enum Foo {
    Bar(Bar),
    Baz(Baz),
    Qux,
}

fn main() {
    let foo = Foo::Bar(Bar(42));

    let foo = match foo {
        Foo::Bar(bar) => bar.0.to_string(),
        Foo::Baz(baz) => baz.s,
        Foo::Qux => "".to_owned(),
    };
    
    assert_eq!(foo, "42");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM