2017-02-11 44 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

相關問題