Макрос ракетки, генерирующий ошибку вложенного модуля

Экспериментируя с макросами ракетки, я наткнулся на определение, которое поначалу не было для меня очевидным, почему оно было отклонено. Код короткий и, вероятно, бесполезен, но выглядит так:

#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 из (go 'dummy) это связано #lang racket не распознается как одна и та же привязка в моде submodule, хотя синтаксически это та же последовательность букв. Если я уберу манекен из всего лексического контекста путём кругового отключения следующим образом:

(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 ответ

Решение

Выражение, которое вы вставляете для id в:

(module mod racket
  (define it 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

В большинстве макросов хорошо, что контекст сохраняется, поэтому мне кажется, что "убрать", чтобы удалить его, нормально.

Конечно, если вы испытываете много к котельной плите, то напишите макрос, который вставляет котельную плиту для вас:-)

Другие вопросы по тегам