2016-06-10 90 views
8

我在Rust中使用宏並想要進行嵌套擴展,即combinatorics。Rust宏中的嵌套迭代

這是我寫的代碼:

macro_rules! nested { 
    (
     $(arg $arg:ident;)* 
     $(fun $fun:ident;)* 
    ) => { 
     $(
      $fun($($arg),*); 
     )* 
    } 
} 

fn show1(a: i32, b: i32, c: i32) { 
    println!("show1: {} {} {}", a, b, c); 
} 
fn show2(a: i32, b: i32, c: i32) { 
    println!("show2: {} {} {}", a, b, c); 
} 

fn main() { 
    let a = 1; 
    let b = 2; 
    let c = 3; 
    nested! { 
     arg a; 
     arg b; 
     arg c; 
     fun show1; 
     fun show2; 
    } 
} 

Playground

我想這個擴大到

fn main() { 
    let a = 1; 
    let b = 2; 
    let c = 3; 
    // iteration over $fun 
    show1(/* iteration over $arg */a, b, c); 
    show2(/* iteration over $arg */a, b, c); 
} 

然而,似乎鏽不支持這一點,相反抱怨:

error: inconsistent lockstep iteration: 'fun' has 2 items, but 'arg' has 3 

顯然它忽略了內部迭代。

但是,如果我刪除了參數的個數爲一體,使之2項兩種,它仍然抱怨:

<anon>:7:18: 7:25 error: attempted to repeat an expression containing no 
        syntax variables matched as repeating at this depth 
<anon>:7    $fun($($arg),*); 

有沒有辦法做我想要什麼?

回答

6

看來這是不可能做這種擴張。這裏是一個解決辦法:

macro_rules! nested { 
    ($(arg $arg:ident;)* $(fun $fun:ident;)*) => { 
     // expand arg to a tuple that will be matched as tt 
     // in @call_tuple an will be decomposed back to 
     // a list of args in @call 
     nested!(@call_tuple $($fun),* @ ($($arg),*)) 
    }; 
    (@call_tuple $($fun:ident),* @ $tuple:tt) => { 
     $(nested!(@call $fun $tuple))* 
    }; 
    (@call $fun:ident ($($arg:expr),*)) => { 
     $fun($($arg),*); 
    }; 
} 

@id僅用於internal守規則的宏。