【问题标题】:Pattern matching the tag of a tagged union enum匹配标记联合枚举的标记的模式
【发布时间】:2015-04-08 00:35:57
【问题描述】:

有没有办法提取枚举的标签,例如,将其用作索引?

我想要一个按枚举类型分类的向量的向量,即,如果我有:

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

我可能想要这样的向量:

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

在给定新值的情况下,我想动态地添加到这个向量中。因此,如果一个函数在 Test::Number 中传递,它将进入第二个数组。

当然,在最坏的情况下,我可以显式地匹配每个可能的联合值,但是对于大型枚举,这会变得相当冗长和重复,因为所有的情况都会结束

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
}

我已经尝试了很多语法排列,但我没有得到任何可以编译的东西。有没有办法将枚举结构标签视为枚举?看起来有一个 FromPrimitive 派生,但它不稳定并且不适用于结构枚举。

(如果你不能,我想另一个问题是你是否可以编写一个宏来自动写入该匹配项)。

【问题讨论】:

标签: rust


【解决方案1】:

您可以使用.. 忽略枚举的所有字段,无论有多少,您可以使用useenums 命名空间内导入变体。例如

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

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

【讨论】:

    【解决方案2】:

    您可以在枚举上的匹配臂和方法中使用交替语法(通过|)来减少代码重复:

    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,
            }
        }
    }
    

    【讨论】:

    • 我认为我的问题可能并不完全清楚。我基本上想使用 name 作为索引。所以 Point1、Point2、Point3 等都是它们自己的唯一 ID。我想,我基本上想要一个将每个唯一枚举值映射到 u32 的映射。函数和模式匹配是可以接受的,但在我的情况下这并没有真正浓缩它。
    • @Jsor 将所有这些作为枚举值的方法写一次仍然可以减少代码重复,但会留下一个冗长的方法。
    • 我想问题是我希望能够在不更改其他地方的代码的情况下添加到枚举中。虽然我猜如果我忘记了,至少编译器会因为不详尽而困扰我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    相关资源
    最近更新 更多