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

时间:2015-06-17 09:20:41

标签: macros rust

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

unroll_loop!(f, a, 3);

生成

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

1 个答案:

答案 0 :(得分:9)

好吧,有点

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

您可能会想问“为什么不使用unroll!($i-1, |$i| $s)来表示递归情况?”。这是因为宏不能做数学。事实上,他们不能任何形式的评估无论如何。你基本上只限于象征性的操纵。

不能以任何方式与类型或值进行交互,这意味着以下不起作用,无法使用

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

所以,可以执行此操作,但仅适用于文字整数,并且您必须在宏中为每个想要能够使用的整数编写一个明确的大小写。