将单个枚举变量映射到Rust中的Result的惯用方法是什么?

时间:2017-03-20 14:35:45

标签: enums rust

我的枚举类型定义为

enum MyEnum {
    Foo(SomeType),
    Bar(SomethingElse),
    Baz(YetAnotherThing),
    ...
}

我经常需要在Result - 返回函数的上下文中匹配单个案例。更具体地说,我写这样的代码:

impl MyEnum {
    fn as_foo(&self) -> Result<&SomeType, Error> {
        if let MyEnum::Foo(x) = y {
            Ok(&x)
        } else {
            Err(MismatchError)
        }
    }

    fn as_bar(&self) -> Result<&SomethingElse, Error> {
         ...
    }

    ...

}

以后我可以做

let x = myenum.as_foo()?

而不是更麻烦的

if let MyEnum::Foo(x) = myenum {
    ...
} else {
    return Err(MismatchError);
}

当然,有一种更有效的方法来获得这种效果,而不是手工为每种可能的变体编写方法?语言中是否有某种东西,或者我应该研究自己写的宏?

我不清楚如何处理有多个字段或有命名字段的情况。前者可能通过一个元组?后者我总是可以通过引入中间结构来减少。

1 个答案:

答案 0 :(得分:1)

您可以使用简单的访问者宏来执行此操作:

macro_rules! try_unpack {
    ($variant:path, $value:expr) => {
        if let $variant(x) = $value {
            x
        } else {
            return Err(MismatchError)
        }   
    }
}

struct SomeType;
struct SomethingElse;
struct YetAnotherThing;

enum MyEnum {
    Foo(SomeType),
    Bar(SomethingElse),
    Baz(YetAnotherThing)
}

struct MismatchError;

fn test(x: MyEnum) -> Result<i32, MismatchError> {
    let y: SomethingElse = try_unpack!(MyEnum::Bar, x);
    return 42;
}