简体   繁体   中英

Pattern matching the tag of a tagged union enum

Is there a way to extract the tag of an enum to, eg, use it as an index?

I'd like to have a vector of vectors classified by enum type, ie, if I had:

enum Test {
    Point {
        x: i32,
        y: i32,
    },
    Point2 {
        a: i32,
        b: i32,
    },
    Number(i32),
}

I may want a vector like this:

[[Test::Point{1, 2}, Test::Point{3, 4}], [Test::Number(1), Test::Number(2)]] 

I'd like to dynamically add to this vector of vectors given new values. So if a function was passed in a Test::Number , it would go in the second array.

Certainly in the worst case I could explicitly pattern match every possible union value, but for large enums that would get rather verbose and repetitive since all the cases would just end up as

match e {
    Test::Point { _, _ } => v[0].push(e),
    Test::Point2 { _, _ } => v[1].push(e),
    Test::Number(_) => v[2].push(e),
    // imagine a lot of these
}

I've tried a lot of syntax permutations, but I haven't gotten anything that will compile. Is there a way to treat the enum struct tags like, well, an enumeration? It looks like there's a FromPrimitive derive, but it's unstable and doesn't work on struct enums.

(I suppose an alternative question if you can't is if you can write a macro to autowrite that match).

You can use .. to ignore all fields of an enum, no matter how many there are, and you can import variants from inside the enum s namespace with use . Eg

enum Foo {
   X { i: u8 },
   Y(u8),
   Z
}

fn bar(x: Foo) -> u32 {
    use Foo::*;
    match x {
        X { .. } => 100,
        Y(..) => 3,
        Z => 12,
    }
}

You can use the alternation syntax (via | ) in the match arms and methods on the enum to reduce code duplication:

enum Test {
    Point1,
    Point2,
    Point3,
    Point4,
    Number1,
    Number2,
    Number3,
    Number4,
}

impl Test {
    fn bucket(&self) -> u8 {
        use Test::*;
        match *self {
            Point1 | Point2 | Point3 | Point4 => 0,
            Number1 | Number2 | Number3 | Number4 => 1,
        }
    }
}

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