首页 文章

语法参数可以用来替换语法吗?

提问于
浏览
0

我正在尝试使用语法参数,以便在我需要注入的地方注入新语法 . 然后在其他语法中使用此结果 . 但是,它没有像我期望的那样工作 . 这是一个最小的工作示例:

(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

EDIT:

发布了一个新问题来改进问题:Injecting syntax at compile time using Racket's syntax parameters?

1 回答

  • 2

    这里的问题是你的 print-syntax 宏引用它的输入,宏转换器的输入是未扩展的语法 . 这意味着 (print-syntax placeholder) 的扩展将始终为 (displayln 'placeholder) ,并且 quote 下不会发生宏扩展,因此范围内的 placeholder 绑定无关紧要 .

    如果要使用语法参数,则需要实际生成对 placeholder 绑定的引用 . 在这种情况下,您只需要删除 quote 的使用 . 您可以将 print-syntax 更改为 (displayln arg) ,但此时, print-syntax 确实没有理由成为宏,因为它等同于 displayln 函数 . 只需使用它:

    (declare-many-commands
     (displayln placeholder))
    

    这将按预期打印 1020 .

    你可能真的想要 quote ,我不明白你的问题 . 但是,在这种情况下,我认为在没有其他背景的情况下,我很难理解你所得到的东西 .

相关问题