1

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

#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)那么它可以工作。我有一种预感,'即。即使在语法上它是相同的字母序列,在子模块 mod 中也不会被识别为相同的quote绑定(go 'dummy)#lang racket如果我通过往返来去除所有词汇上下文的虚拟,如下所示:

(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没有这个样板真的一样吗?

4

1 回答 1

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

在大多数宏中,保留上下文是一件好事,因此必须“样板”来删除它对我来说似乎没问题。

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

于 2018-07-15T21:45:50.007 回答