Makro (Metaprogrammierung)
Kurz: Ein Makro ist Code, der beim Übersetzen anderen Code erzeugt oder umschreibt. Es erweitert die Sprache selbst und spart Wiederholungen.
Genauer: Es gibt einfache Textersetzung (C-Präprozessor: #define) und mächtige Syntax-Makros, die mit dem Syntaxbaum arbeiten (Lisp, Racket, Rust, Nim, Elixir, Julia). Letztere sind hygienisch, wenn Namen im Makro nicht mit Namen des Aufrufers kollidieren.
Im Detail
#define QUADRAT(x) ((x) * (x)) // Textersetzung; Klammern sind Pflicht!
int a = QUADRAT(3 + 1); // ((3 + 1) * (3 + 1)) = 16(defmacro wiederhole (n &body rumpf)
`(dotimes (i ,n) ,@rumpf))
(wiederhole 3 (print "Hallo"))macro_rules! maximum {
($a:expr) => ($a);
($a:expr, $($rest:expr),+) => {{ let r = maximum!($($rest),+); if $a > r { $a } else { r } }};
}
println!("{}", maximum!(3, 9, 4)); // 9Wofür?
- Neue Kontrollstrukturen (
unless,with-open-file,try-with-resources) - Fachsprachen (DSLs), zum Beispiel für Abfragen oder Tests
- Code-Erzeugung aus Daten (Serialisierung, Parser)
- Bedingte Übersetzung (
#ifdef DEBUG)
Risiken
Textmakros sind fehleranfällig (Mehrfachauswertung von Argumenten: QUADRAT(i++)), und viele Makros machen Code schwer zu lesen. Faustregel: erst Funktion, dann Makro – nur wenn sich etwas ohne Makro nicht ausdrücken lässt.
Ausführliche Makro-Kapitel enthalten die Kurse Common Lisp, Racket, Scheme und Nim. Zur Laufzeit arbeitet dagegen Reflection.
Siehe auch: Reflection, Annotationen, Compiler, Lambda-Ausdruck