定义和语法宏如何在 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++ 宏),这两个程序的行为将完全相同,但显然它们并非如此。似乎出现在语法宏调用中的标识符在某种程度上是“特殊的”,使用它们的 define
s 与不使用它们的 define
s 表现不同。此外,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))
我是 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++ 宏),这两个程序的行为将完全相同,但显然它们并非如此。似乎出现在语法宏调用中的标识符在某种程度上是“特殊的”,使用它们的 define
s 与不使用它们的 define
s 表现不同。此外,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))