我尝试使用语法参数,以便在我需要注入的地方注入新语法。然后在其他语法中使用此结果。 但是,它没有像我期望的那样工作。这是一个最小的工作示例:
(require racket/stxparam)
(require (for-syntax racket/stxparam))
;; declare parameter to be replaced with code
(define-syntax-parameter placeholder
(lambda (stx)
(raise-syntax-error
(syntax-e stx)
"can only be used inside declare-many-commands")))
;; this is just to print what 'arg' looks like
(define-syntax (print-syntax stx)
(syntax-case stx ()
[(_ arg)
#'(displayln 'arg)]))
;; this is the top-level entity invoked to produce many commands
(define-syntax-rule (declare-many-commands cmds)
(begin
(let ([X 10])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))
(let ([X 20])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))))
(declare-many-commands
(print-syntax placeholder))
运行它时我想得到的结果是:
10
20
但我得到的是:
placeholder
placeholder
修改
发布了一个新问题来改进问题:Injecting syntax at compile time using Racket's syntax parameters?
答案 0 :(得分:2)
这里的问题是你的print-syntax
宏引用它的输入,宏转换器的输入是未展开的语法。这意味着(print-syntax placeholder)
的扩展将始终为(displayln 'placeholder)
,并且quote
下不会发生宏扩展,因此范围内的placeholder
绑定无关紧要。
如果要使用语法参数,则需要实际生成对placeholder
绑定的引用。在这种情况下,您只需要删除quote
的使用。您可以将print-syntax
更改为(displayln arg)
,但此时,print-syntax
确实没有理由成为宏,因为它等同于displayln
函数。只需使用它:
(declare-many-commands
(displayln placeholder))
这将按预期打印10
和20
。
你可能真的想要quote
,我不明白你的问题。但是,在这种情况下,我认为如果没有其他背景,我很难理解你的目标。