2016-06-10 18 views
8

Rust'ta makrolarla oynuyorum ve iç içe genişletme yapmak istiyorum, yani birleştirici. Pas makroları içinde iç içe yineleme

Bu

Yazdığım kod şudur: Ben bu Ancak

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); 
} 

genişletmek istiyorum

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

, bu Pas bu desteklemediği görünüyor ve bunun yerine şikayetler:

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

Görünüşe göre, iç yinelemeyi yok sayar.

Ancak, ben her ikisi için bunu 2 öğe yapmak için, args birini kaldırırsanız, hala yakınır:

<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),*); 

İstediğimi yapmak için bir yolu var mı?

cevap

6

Bu tür bir genişleme yapmak mümkün görünmüyor.

@id
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),*); 
    }; 
} 

sadece makroya kurallarını internal tutmak için kullanılır: Burada bir geçici çözümdür.

İlgili konular