定义和语法宏如何在 Racket 中交互?

How do defines and syntax macros interact in Racket?

我是 Racket 的新手,有些语法宏我不明白。我有这两个程序:

这个,正确执行:

#lang racket

(define-syntax-rule (create name) (define name 2))

(create x)

(displayln (+ x 3))

还有这个抱怨标识符 x 未绑定:

#lang racket

(define-syntax-rule (create) (define x 2))

(create)

(displayln (+ x 3))

使用简单的替换方法(例如 C/C++ 宏),这两个程序的行为将完全相同,但显然它们并非如此。似乎出现在语法宏调用中的标识符在某种程度上是“特殊的”,使用它们的 defines 与不使用它们的 defines 表现不同。此外,Racket 标准库中有 struct 语法宏,它定义了几个在其调用中未明确命名的变量,例如:

(struct employee (first-name last-name))

将定义 employee?employee-first-name,它们都没有在调用中直接命名。

这是怎么回事,可以解决这个问题,以便我可以创建 struct 的自定义版本?

天真的替换的问题是无意的捕获。默认情况下,球拍宏是卫生的,这意味着它避免了这个问题。有关详细信息,请参阅 https://en.wikipedia.org/wiki/Hygienic_macro

也就是说,宏系统也支持不卫生的宏。 struct 是一个不卫生的宏的例子。但是您需要付出更多努力才能使不卫生的宏正常工作。

例如,您的 create 的第二个版本可以这样写:

#lang racket

(require syntax/parse/define)

(define-syntax-parse-rule (create) 
  #:with x (datum->syntax this-syntax 'x)
  (define x 2))

(create)

(displayln (+ x 3))