我正在尝试在Rust中编写一些快速矩阵代码,并且需要确保循环展开.有没有办法创建一个编译时for循环?例如:我想要
unroll_loop!(f, a, 3);
Run Code Online (Sandbox Code Playgroud)
生成
f(a, 0);
f(a, 1);
f(a, 2);
Run Code Online (Sandbox Code Playgroud)
好吧,有点.
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));
}
Run Code Online (Sandbox Code Playgroud)
您可能会想问"为什么不unroll!($i-1, |$i| $s)用于递归案例?".这是因为宏不能做数学运算.事实上,他们不能做任何形式的评价任何.你基本上只限于象征性的操纵.
宏也无法以任何方式与类型或值进行交互,这意味着以下内容不起作用,并且无法工作:
const N: usize = 3;
unroll!(N, |i| println!("i: {}", i));
Run Code Online (Sandbox Code Playgroud)
所以,你可以这样做,但只能用于文字整数,并且你必须在宏中为每个想要能够使用的整数写一个显式的例子.