Rust宏中的嵌套迭代

Seb*_*edl 9 rust

我正在使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

操场

我想要扩展到

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);
}
Run Code Online (Sandbox Code Playgroud)

但是,似乎Rust不支持这一点,而是抱怨:

error: inconsistent lockstep iteration: 'fun' has 2 items, but 'arg' has 3
Run Code Online (Sandbox Code Playgroud)

显然它忽略了内在的迭代.

但是,如果我删除其中一个args,为两个都做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),*);
Run Code Online (Sandbox Code Playgroud)

有办法做我想要的吗?

mal*_*rbo 8

似乎不可能进行这种扩展.这是一个解决方法:

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),*);
    };
}
Run Code Online (Sandbox Code Playgroud)

@id仅用于保持规则内部的宏.