scheme
Schematy Makra
Szukaj…
Higieniczne i referencyjnie przezroczyste makra z regułami składni
Największą przewagą LISP i Scheme nad innym głównym językiem programowania jest ich system makr. W przeciwieństwie do preprocesora C i innych języków makr, makra Schematu pobierają analizowany kod jako dane wejściowe i zwracają kod rozszerzony jako dane wyjściowe. Jest to jedna z aplikacji wyrażenia Schemat „kod to dane” i to czyni język tak potężnym.
Makra w schemacie są tworzone przy użyciu define-syntax , która może definiować makro na wiele sposobów. Najprostszą metodą jest użycie syntax-rules , które wykorzystują dopasowanie wzorca do przekształcenia kodu wejściowego w kod wyjściowy.
W tym przykładzie utworzono prostą składnię dla for item in list i for list as item składni for list as item do zapętlania elementów na liście:
(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 ...))))
Te dwa makra mogą być następnie używane w następujący sposób, zapewniając bardziej imperatywny styl:
(let ((names '(Alice Bob Eve)))
(for name in names
(display "Hello ")
(display name)
(newline))
(for names as name
(display "name: ")
(display name)
(newline)))
Uruchomienie kodu zapewni oczekiwany wynik:
Hello Alice
Hello Bob
Hello Eve
name: Alice
name: Bob
name: Eve
Najczęstszym błędem, na który należy zwrócić uwagę, jest nieprzekazanie poprawnych wartości do makra, co często skutkuje nieprzydatnym komunikatem o błędzie, który dotyczy rozszerzonej formy zamiast wywołania makra.
Powyższe definicje składni for nie sprawdzają, czy przekazano im identyfikator i listę, więc przekazanie dowolnego innego typu spowoduje błąd wskazujący na wywołanie for-each zamiast wywołania for . Debugowanie tego przeczy celowi makra, więc to użytkownik musi wprowadzić tam kontrole i zgłosić błędy użytkowania, które następnie można wykryć podczas kompilacji.