生成嵌套模块错误的 Racket 宏

Racket macro that generates a nested module error

在试验 racket 的宏时,我偶然发现了一个定义,起初我并不清楚它被拒绝的原因。代码很短,否则可能没用,但如下:

#lang racket
(define-syntax (go stx)
  (syntax-case stx ()
    [(_ id)
     #'(module mod racket
         (define it id))]
    ))
(go 'dummy)

投诉是quote: unbound identifier; also, no #%app syntax transformer... 如果我手动将 (define it id) 内联到 (define it 'dummy) 那么它就可以工作。 我有一种预感 ' 即。由 #lang racket 绑定的 (go 'dummy)quote 在子 mod 规则 mod 中不被识别为相同的绑定,即使在句法上它是相同的序列字母。如果我按如下所示通过往返去除所有词汇上下文的虚拟:

(with-syntax ([ok (datum->syntax #f (syntax->datum #'id))])

下面的模式匹配 (_ id) 并将 it 的定义替换为 (define it ok) 然后一切都很好。

#lang racket
(define-syntax (go stx)
  (syntax-case stx ()
    [(_ id)
     (with-syntax ([ok (datum->syntax #f (syntax->datum #'id))])
       #'(module mod racket
           (define it ok)))]
    ))
(go 'dummy)

我认为我的困境是由卫生系统引起的。但是,是否有更直接的解决方案来说服球拍编译器这些标识符,即。 quote没有这个样板真的一样吗?

您为 id 插入的表达式:

(module mod racket
  (define it id))

将在模块的上下文中进行评估。 因此句法上下文 id id 需要与 子模块的上下文。

您描述了一种删除现有上下文的方法。这是另一个:

#lang racket
(require (for-syntax racket/base))

(define-syntax (go stx)
  (syntax-case stx ()
    [(_ id)
     (with-syntax ([id (syntax->datum #'id)])
       #'(module mod racket
           (provide it)
           (define it id)))]))

(go 42)
(require (submod "." mod))
it

在大多数宏中,保留上下文是一件好事,所以 不得不 "boiler plate" 删除它对我来说似乎没问题。

当然,如果你经验丰富,那就写吧 为您插入样板的宏 :-)