scheme
Schema Makros
Suche…
Hygienische und referenziell transparente Makros mit Syntaxregeln
Der größte Vorteil von LISP und Scheme gegenüber anderen Mainstream-Programmiersprachen ist das Makrosystem. Im Gegensatz zum C-Präprozessor und anderen Makrosprachen nehmen Schema-Makros geparsten Code als Eingabe entgegen und geben erweiterten Code als Ausgabe zurück. Dies ist eine der Anwendungen des Schemas „Code is Data“ -Satz, und dies macht die Sprache so mächtig.
Makros im Schema werden mit einer define-syntax erstellt, die ein Makro auf verschiedene Arten definieren kann. Die einfachste Methode ist die Verwendung von syntax-rules , mit denen der Eingabecode in Mustercode umgewandelt wird.
In diesem Beispiel wird ein einfaches for item in list und for list as item zum Durchlaufen von Elementen in einer Liste erstellt:
(define-syntax for
(syntax-rules (in as) ; 'in' and 'as' keywords must match in the pattern
; When the 'for' macro is called, try matching this pattern
((for element in list
body ...) ; Match one or more body expressions
; Transform the input code
(for-each (lambda (element)
body ...)
list))
; Try matching another pattern if the first fails
((for list as element
body ...)
; Use the existing macro for the transform
(for element in list
body ...))))
Diese beiden Makros können dann wie folgt verwendet werden, um einen zwingenden Stil zu bieten:
(let ((names '(Alice Bob Eve)))
(for name in names
(display "Hello ")
(display name)
(newline))
(for names as name
(display "name: ")
(display name)
(newline)))
Das Ausführen des Codes liefert die erwartete Ausgabe:
Hello Alice
Hello Bob
Hello Eve
name: Alice
name: Bob
name: Eve
Der häufigste Fehler, nach dem Sie Ausschau halten müssen, ist, die korrekten Werte nicht an ein Makro zu übergeben. Dies führt häufig zu einer nicht hilfreichen Fehlermeldung, die für das erweiterte Formular und nicht für den Makroaufruf gilt.
Bei den for Syntaxdefinitionen wird nicht geprüft, ob ihnen ein Bezeichner und eine Liste übergeben wird. Wenn Sie einen anderen Typ übergeben, wird ein Fehler angezeigt, der auf den for-each Aufruf statt auf den for Aufruf verweist. Durch das Debuggen wird der Zweck des Makros vereitelt. Es liegt also am Benutzer, die Überprüfungen dort einzulegen und Nutzungsfehler zu melden, die dann beim Kompilieren abgefangen werden können.