我是Racket和Lisp的初学者,并且正在使用语法定义。我定义了一个简单的转换,如下所示:

(define-syntax hello
  (syntax-rules (in)
    ((_ name in world) (format "Hello ~a in ~a" name world))
    ((_ in name) (format "Hello ~a in here" name))))


现在,当我以这两种情况运行它时,它可以正常工作:

(hello "me" in "world") === "Hello me in world"


和,

(define in "inside")
(hello me in in)  === "Hello me in inside"


但是,这会导致错误,

(let ([in "Shire"])
  (hello "Martin" in in)) === Error: hello: bad syntax in: (hello "Martin" in in)


那么,hello在let绑定内失败的原因是什么,而对定义却很好?另外,在哪里可以获得有关此差异的更具体的信息?谢谢。

最佳答案

这与语法文字的工作方式有关。特别地,如果满足以下条件,则认为语法文字是匹配的:


文字在宏定义时没有绑定,在宏使用时也没有绑定。
文字在宏定义时具有绑定,并且在宏使用时也具有相同的绑定。


define案例对您有用,因为您可能将define放在了与宏相同的模块中。这意味着符合条件2:in在宏定义和用法上具有相同的绑定。但是,如果在一个模块中定义了宏(对于define没有in),并且在使用宏的另一个模块中定义了in,那么事情将无法正常进行。 :-)

let案例为in创建新的绑定。这将永远与顶级宏定义中in的绑定不匹配。

08-26 19:10
查看更多