2017-03-31 13 views
7

は、私が何をしたいの合成例を示しますマクロでオプションの後続カンマを許可するにはどうすればよいですか?ここ

macro_rules! define_enum { 
    ($Name:ident { $($Variant:ident),* }) => { 
     pub enum $Name { 
      None, 
      $($Variant),*, 
     } 
    } 
} 

define_enum!(Foo { A, B }); 

このコードはコンパイルされ、それにカンマを追加した場合:

define_enum!(Foo { A, B, }); 
//     ^

コンパイルが失敗しました。私はそれを修正することができます:

($Name:ident { $($Variant:ident,)* }) 
//       ^

が、その後define_enum!(Foo { A, B });は失敗し、

は、どのように私は両方のケースを処理するためのマクロを記述する必要があります

define_enum!(Foo { A, B }); 
define_enum!(Foo { A, B, }); 

答えて

11

あなたがで...取り扱い両方のケースを扱うことができますどちらの場合も:

macro_rules! define_enum { 
    ($Name:ident { $($Variant:ident,)* }) => { 
     pub enum $Name { 
      None, 
      $($Variant),*, 
     } 
    }; 
    ($Name:ident { $($Variant:ident),* }) => { 
     define_enum!($Name { $($Variant,)* }); 
    }; 
} 

define_enum!(Foo1 { A, B }); 
define_enum!(Foo2 { A, B, }); 

fn main() {} 

主な実装をexp末尾のカンマを改行します。次に、カンマがない場合と一致する2番目の句を追加し、コンマでバージョンに書き換えます。末尾のカンマ自体をオプションに


DK. points out an alternative、:

($Name:ident { $($Variant:ident),* $(,)* }) => { 

これは、他の1つの実装から委任する必要がありません。錆の毎晩のバージョンでは

、あなたはより明白な方法でこれを書いて、複数の末尾のカンマを許可しないようにmacro_at_most_once_rep機能を使用することができます。

($Name:ident { $($Variant:ident),* $(,)? }) => { 
//         ^
+1

あなたは '$(、)を使用することができるのに、なぜそれを気に* 'マクロパターンの閉じ括弧の直前? 1つのルールは、コンマの後ろに機能します。さて、それはspec *の* little *ですが、繰り返しに大いに削減します。 –

+1

@DK。主な理由は、私があなたがそれを行うことができると気付かなかったからです;-)私にとって完全に激しい答えのように聞こえます。それを追加してください! – Shepmaster

+0

あなたは最初にここにいました。あなたはすでに無意味なインターネットポイントを4つ持っています。両方の中で最高の選択肢としてあなたのものを編集するのが早い。 –

関連する問題