Ну, рода.
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));
Таким образом, вы можете это сделать , но только для литеральных целых чисел, и вам нужно написать явный случай в макросе для каждого целого числа, которое захочет использовать.
Я думаю, что вы можете написать расширение синтаксиса для этого, но регулярные макросы macro_rules не помогут вам, потому что у них нет доступных для них переменных или номеров. –