Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust宏中的嵌套迭代_Rust - Fatal编程技术网

Rust宏中的嵌套迭代

Rust宏中的嵌套迭代,rust,Rust,我在Rust中玩宏,想做嵌套扩展,即组合数学 这是我写的代码: macro_rules! nested { ( $(arg $arg:ident;)* $(fun $fun:ident;)* ) => { $( $fun($($arg),*); )* } } fn show1(a: i32, b: i32, c: i32) { println!("show1: {} {

我在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;
    }
}

我想把这个扩展到

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);
}
然而,Rust似乎并不支持这一点,而是抱怨:

错误:锁步迭代不一致:“fun”有2项,但“arg”有3项
显然,它忽略了内部迭代

但是,如果我删除其中一个参数,使其成为两个项目,它仍然会抱怨:

:7:18:7:25错误:试图重复包含no的表达式
语法变量匹配为在此深度重复
:7$fun($($arg),*);

有什么方法可以实现我想要的吗?

似乎不可能实现这种扩展。以下是一个解决方法:

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
仅用于将规则保留在宏中。

这里是一种稍微简单的方法

macro\u规则!嵌套{
($($f:ident),*)$args:tt)=>{
$(嵌套!(@call$f$args);)*
};
(@call$f:ident($($arg:expr),*)=>{
$f($($arg),*);
};
}
嵌套的!{
(图1、图2)
(a、b、c)
}
与@malbarbo的答案相同,但将宏更改为将args放在括号中。然后,您可以接受args作为单个标记,以便在第一次扩展中仅重复函数名