产生嵌套模块错误的球拍宏

时间:2018-07-15 20:09:59

标签: macros racket hygiene

在尝试使用球拍的宏时,我偶然发现了一个定义,该定义最初对我来说并不明显,为什么它被拒绝了。代码简短,否则可能没用,但是如下:

#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),则可以正常工作。 我有个'的预感,即。 quote的{​​{1}}中受(go 'dummy)绑定的#lang racket在子模块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真的没有这个样板吗?

1 个答案:

答案 0 :(得分:0)

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

在大多数宏中,保留上下文是一件好事,因此 对我来说,必须“锅炉板”将其卸下似乎可以。

当然,如果您遇到很多样板,那就写 一个为您插入样板的宏:-)