如何在宏中用嵌套循环迭代多个参数?

3

以下代码:

macro_rules! test {
    ( $( $x1:expr ),*; blub $( $x2:expr ),* ) => {
        $(
            println!("{} * {} = {}", $x1, $x2, $x1 * $x2);
        )*
    }
}

fn main() {
    test!{1, 2, 3; blub 4, 5, 6};
}

输出:

1 * 4 = 4
2 * 5 = 10
3 * 6 = 18

然而,我想分别循环遍历这两个列表,就像一个嵌套循环一样。它应该打印出:
1 * 4 = 4
1 * 5 = 5
1 * 6 = 6
2 * 4 = 8
2 * 5 = 10
2 * 6 = 12
3 * 4 = 12
3 * 5 = 15
3 * 6 = 18

我该怎么做?

2个回答

2
我找到的唯一方法是通过在参数中使用令牌树来轻微地欺骗,就像这样:
macro_rules! test {
    // secondary invocation with a `[]` delimited list of parameters
    // as the first arguments and a single second argument.
    ( [ $( $x1:expr),* ] ; $x2:expr ) => {
        $(
            println!("{:?} * {:?} = {:?}", $x1, $x2, $x1 * $x2);
        )*
    };

    // the main invocation of the macro, takes a token tree `x1`
    // and a `[]` delimited `,` separated list of arguments for
    // each of which it calls itself again with `x1` as first
    // parameter and the element of the list as the second
    ( $x1:tt [ $( $x2:expr ),* ] ) => {
        $(
            test!($x1; $x2);
        )*
    };
}

fn main() {
    test!{
        [1, 2, 3]
        [4, 5, 6]
    };
}

谢谢!我会接受两个答案,但我发现另一个更容易理解一些。 - Michael Mahn

1

你需要使用嵌套循环,因为你需要迭代一个可变数量的 x2。你可以将每个重复的标记分别展开成一个数组,并以与任何可迭代集合相同的方式循环遍历它:

macro_rules! test {
    ( $($x1:expr ),*; blub $($x2:expr ),* ) => {
        for x1 in [$($x1),*] {
            for x2 in [$($x2),*] {
                println!("{} * {} = {}", x1, x2, x1 * x2);
            }
        }
    }
}

fn main() {
    test!{1, 2, 3; blub 4, 5, 6};
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接