2017-03-20 13 views
2

私は単一の列挙型をRustのResultにマッピングする慣習的な方法は何ですか?

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

として定義列挙型を持っていると私はしばしばResult -returning機能の文脈の中で、一つのケースで一致する必要があります。具体的には、私はこのようなコードを書く:

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> { 
     ... 
    } 

    ... 

} 

だから、後で私が代わりに面倒

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

let x = myenum.as_foo()? 

を行うことができます確かに取得するためのより効率的な方法がありますその可能性のあるバリアントごとにメソッドを手作業で書くよりも効果がありますか?すでに言語に何かがあるのですか?自分のマクロを研究する必要がありますか?

フィールドが複数ある場合や名前付きフィールドがある場合を処理する方法は私には分かりません。前者はおそらくタプルを通っているでしょうか?後者は中間構造体を導入することでいつも減らすことができます。

+0

私は唯一のケースのために、自動的に私のためにこれらのアクセサを生成するための手続きマクロ( 'is_foo'、' as_foo'、 'into_foo')を書きました単一のメンバ変数のうち、同じコードを生成します。 – Shepmaster

答えて

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; 
} 
+3

私はいつもコントロールフローを隠しているマクロに不快です。代わりにゲッターを生成するためにマクロを使用しないでください。 –

関連する問題