2015-06-17 4 views
9

Ich versuche, in Rust einen schnellen Matrix-Code zu schreiben und dafür zu sorgen, dass Schleifen abgerollt werden. Gibt es eine Möglichkeit, eine Kompilierungszeit für eine Schleife zu erstellen? Z. B: Ich möchteKann ich ein Makro erstellen, das Schleifen abrollt?

unroll_loop!(f, a, 3); 

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

Ich denke, dass Sie eine Syntaxerweiterung dafür schreiben können, aber normale 'macro_rules'-Makros werden Ihnen nicht helfen, weil ihnen keine Arten von Variablen oder Nummern zur Verfügung stehen. –

Antwort

9

Nun, Art zu erzeugen.

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

Sie könnten versucht sein, zu fragen, „warum Sie unroll!($i-1, |$i| $s) einfach nicht für die rekursive Fall verwenden?“. Dies liegt daran, Makros können nicht Mathe tun. In der Tat können sie keine Form der Bewertung was auch immer tun. Sie sind grundsätzlich auf symbolische Manipulation beschränkt.

Makros können auch nicht mit Typen oder Werte in irgendeiner Weise in Wechselwirkung treten, was bedeutet, dass die folgenden nicht funktioniert, und nicht gemacht werden kann arbeiten:

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

Also, Sie können dies tun , aber nur für literale Ganzzahlen, und Sie müssen einen expliziten Fall in das Makro schreiben, damit jede ganze Zahl verwendet werden kann.

+0

Nur für diejenigen, die die Compiler-Plugins von Rust nicht kennen: Eine mögliche Lösung dafür, die mit beliebigen (noch zu Kompilierungszeiten bekannten) Zahlen funktioniert, wäre ein Compiler-Plugin, das ein 'entroll! (...)' -Makro mit der gleichen Semantik ausgibt. Plugins sind jedoch noch nicht stabil. – Regexident

Verwandte Themen