Define 和 let wrt 语法规则关键字之间的区别

sou*_*v.d 2 macros scheme racket

我是 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))))
Run Code Online (Sandbox Code Playgroud)

现在,当我像这两种情况一样运行它时,它工作得很好:

(hello "me" in "world") === "Hello me in world"
Run Code Online (Sandbox Code Playgroud)

和,

(define in "inside")
(hello me in in)  === "Hello me in inside"
Run Code Online (Sandbox Code Playgroud)

但是,这会导致错误,

(let ([in "Shire"])
  (hello "Martin" in in)) === Error: hello: bad syntax in: (hello "Martin" in in)
Run Code Online (Sandbox Code Playgroud)

那么,为什么 hello 在 let 绑定中失败,而对于定义却工作得很好呢?另外,我在哪里可以获得有关这种差异的更多具体信息?谢谢。

Chr*_*ung 5

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

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

define案例对您有用,因为您可能将其define与宏放在同一模块中。这意味着条件 2 匹配:in在宏定义和用法上具有相同的绑定。但是,如果您在一个模块中定义了宏(没有definefor in),并in在使用该宏的另一模块中定义了 the ,那么事情就不会那么顺利了。:-)

let案例创建了一个新的绑定inin这永远不会匹配顶级宏定义的绑定。