I'm trying to write some fast matrix code in Rust and to do this needs to ensure that loops are unrolled. Is there a way to create a compile-time for-loop? E.g: I want
unroll_loop!(f, a, 3);
to generate
f(a, 0);
f(a, 1);
f(a, 2);
Well, sort of.
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));
}
You might be tempted to ask "why don't you just use unroll!($i-1, |$i| $s)
for the recursive case?". This is because macros cannot do math. In fact, they cannot do any form of evaluation whatsoever. You are basically limited to symbolic manipulation.
Macros also cannot interact with types or values in any way, which means the following does not work, and cannot be made to work:
const N: usize = 3;
unroll!(N, |i| println!("i: {}", i));
So, you can do this, but only for literal integers, and you have to write an explicit case in the macro for every integer to want to be able to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With