Der Grund dafür ist ein wenig subtile, weder „sollte“ Arbeit, aber wenn die define
auf der obersten Ebene ist, ist es eigentlich Abspaltungen die Interpretation von syntax-rules
, das ist, wo das Verhalten entsteht.
Wenn Sie the documentation for syntax-rules
schauen, sehen Sie, dass jeder literal-id
die gleiche wie in syntax-case
behandelt wird. Die Dokumentation stellt fest, dass die Literale werden miteinander verglichen unter Verwendung free-identifier=?
:
Ein id
, die die gleichen Bindungs als Ausgang literal-id
eine Syntax Objekt übereinstimmt, der im Sinne der free-identifier=?
eine Kennung mit der gleichen Bindung ist.
Dies bedeutet, dass Literale sind Streichhölzer als Bindungen, nicht als Bezugspunkte.Das heißt, wenn Sie eine lokale Definition von in
in einer let
haben, ist es eine separate Bindung von in
als Literal innerhalb syntax-rules
markiert, so dass sie nicht übereinstimmen. Außerdem werden Kennungen, die mit in einem separaten Modul eingeführt wurden, ebenfalls nicht übereinstimmen.
Interessanterweise wenn in
aus dem Modul ausgeführt wird, die das Makro definiert, importierte dann rename-in
verwenden, die noch umbenannt Bindung arbeiten, weil Racket Spur von Umbenennungen hält und hält sie für die gleiche Bindung sein, auch wenn sie nicht die gleicher Name. Das sind orthogonale Konzepte, auch wenn es manchmal leicht ist, alle Nuancen dieser Idee zu übersehen, aber es ist etwas, was der Hygiene innewohnt.
Zurück zu dem fraglichen Beispiel, warum funktioniert das folgende?
(define-syntax hello
(syntax-rules (in)
((_ name in world) (format "Hello ~a in ~a" name world))
((_ in name) (format "Hello ~a in here" name))))
(define in "inside")
(hello "me" in in)
Nun, Definition Kontexte sind gegenseitig rekursive, so die Definition von in
nach der Makrodefinition wird von syntax-rules
tatsächlich abgeholt. Daher erwartet das hello
Makro tatsächlich die gleiche Bindung wie in
, so dass der Aufruf funktioniert. Wenn jedoch wird hello
von in
in einem separaten Modul definiert, wird der Makroaufruf nicht Arbeit, weil die Bindungen seien anders:
(module hello racket
(provide hello)
(define-syntax hello
(syntax-rules (in)
((_ name in world) (format "Hello ~a in ~a" name world))
((_ in name) (format "Hello ~a in here" name)))))
(require 'hello)
(define in "inside")
(hello "me" in in) ; => hello: bad syntax in: (hello "me" in in)
BTW, ich sehe nur Ihre Frage auf #racket im IRC. Sie sollten definitiv länger als 2 Minuten bleiben. IRC ist meist ein lurk-orientiertes Medium; Sie erhalten die besten Ergebnisse, wenn Sie nur die eigentliche Frage posten (ohne auf jemanden warten zu müssen, um auf eine Antwort "Kann jemand helfen?" zu antworten) und dann 24 Stunden auf eine Antwort warten. :-) (Aber, wie du sehen kannst, konnten sowohl lexi-lambda als auch ich hier antworten, so dass es schließlich funktionierte.) –