Beh, sorta di.
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));
}
Si potrebbe essere tentati di chiedere "perché non basta usare unroll!($i-1, |$i| $s)
per il caso ricorsivo?". Questo perché i macro non possono fare matematica. In realtà, non possono fare qualsiasi modulo di valutazione di qualsiasi. Sei fondamentalmente limitato alla manipolazione simbolica.
Macro anche non può interagire con i tipi o valori in qualsiasi modo, il che significa il seguente non funziona, e non può essere fatto funzionare:
const N: usize = 3;
unroll!(N, |i| println!("i: {}", i));
Quindi, si possibile fare questo , ma solo per interi letterali, e devi scrivere un caso esplicito nella macro per ogni intero che vuoi essere in grado di usare.
fonte
2015-06-17 09:48:49
Penso che si possa scrivere un'estensione di sintassi per questo, ma i normali macro "macro_rules'-non ti aiuteranno perché non hanno alcun tipo di variabile o numero a loro disposizione. –