我可以创建一个展开循环的宏吗?

Can I create a macro that unrolls loops?

我正在尝试用 Rust 编写一些快速矩阵代码,为此需要确保展开循环。有没有办法创建编译时 for 循环?例如:我要

unroll_loop!(f, a, 3);

生成

f(a, 0);
f(a, 1);
f(a, 2);

嗯,有点

macro_rules! unroll {
    (0, |$i:ident| $s:stmt) => {};
    (1, |$i:ident| $s:stmt) => {{ let $i: usize = 0; $s; }};
    (2, |$i:ident| $s:stmt) => {{ unroll!(1, |$i| $s); let $i: usize = 1; $s; }};
    (3, |$i:ident| $s:stmt) => {{ unroll!(2, |$i| $s); let $i: usize = 2; $s; }};
    (4, |$i:ident| $s:stmt) => {{ unroll!(3, |$i| $s); let $i: usize = 3; $s; }};
    // ...
}

fn main() {
    unroll!(3, |i| println!("i: {}", i));
}

您可能想问 "why don't you just use unroll!($i-1, |$i| $s) for the recursive case?"。这是因为 宏不能做数学运算 。事实上,他们不能任何形式的评估无论如何。你基本上仅限于符号操作。

宏也不能以任何方式与类型或值交互,这意味着下面的不起作用,也无法使其起作用:

const N: usize = 3;
unroll!(N, |i| println!("i: {}", i));

因此,您可以 执行此操作,但仅限于文字整数,并且您必须在宏中为每个要使用的整数编写一个明确的案例。