Макрос ракетки, генерирующий ошибку вложенного модуля
Экспериментируя с макросами ракетки, я наткнулся на определение, которое поначалу не было для меня очевидным, почему оно было отклонено. Код короткий и, вероятно, бесполезен, но выглядит так:
#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
В большинстве макросов хорошо, что контекст сохраняется, поэтому мне кажется, что "убрать", чтобы удалить его, нормально.
Конечно, если вы испытываете много к котельной плите, то напишите макрос, который вставляет котельную плиту для вас:-)