2017-02-11 7 views
0

以下の例のような単純な再帰的なマクロを使用して、最初の引数を取って残りの部分をglobします。マクロの最後の引数を再帰的に取る方法は?

macro_rules! count_tts { 
    () => {0usize}; 
    ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)}; 
} 

最後の引数を再帰的に受け取る方法はありますか?

これは、することが可能になる:

  • は逆に、引数を処理します。
(例えば、 see related questionそれらを数える)考慮に ($($head:tt)* $tail:tt)のようなものを以前のすべての引数を取る...しかし、これは動作しません。

答えて

2

マクロパーサーには「バックトラッキング」がありません。したがって、$($head:tt)* $tail:ttで直接これを行うことはできません。しかし、あなたは自分でそれを逆転させることでそれを行うことができます。

macro_rules! concat_reverse { 
    ([] $($reversed:tt)*) => { 
     concat!($(stringify!($reversed)),*) // base case 
    }; 
    ([$first:tt $($rest:tt)*] $($reversed:tt)*) => { 
     concat_reverse!([$($rest)*] $first $($reversed)*) // recursion 
    }; 
} 

fn main() { 
    println!("{}", concat_reverse!([e d c b a])) 
    // output: abcde 
} 

マクロトレースは、次のようになります。

concat_reverse!([e d c b a]) 
== concat_reverse!([d c b a] e) 
== concat_reverse!([c b a] d e) 
== concat_reverse!([b a] c d e) 
== concat_reverse!([a] b c d e) 
== concat_reverse!([] a b c d e) 
== concat!(stringify!(a), stringify!(b), stringify!(c), stringify!(d), stringify!(e)) 

あなたは再帰段階で(例えばカウントのために)いくつかの「地図」と「削減」の操作を行うことができます。

このメソッドは再帰の深さを食べることに注意してください。#![recursion_limit="..."]を呼び出す必要があります。

+0

ありがとうございます。ここで私自身の質問に答えるためにこれを使いました:http://stackoverflow.com/a/42176533/432509 'apply_args_reverse'マクロは既存のマクロの引数を逆にすることができるので、他の人にとっては有用かもしれません。 – ideasman42

関連する問題