syntax-parameterize
обычно используется в сочетании с make-rename-transformer
так, что синтаксис-параметр p
ведет себя как псевдоним для другого идентификатора:параметр синтаксиса, указывающий на переменную синтаксиса-шаблона?
#lang racket
(require racket/stxparam)
(define-syntax-parameter p #f)
(define-syntax (test-1-p stx)
(syntax-case stx()
[(_ body)
#'(let ([tmp 123])
(syntax-parameterize ([p (make-rename-transformer #'tmp)])
body))]))
(test-1-p p) ;; prints 123
Код выше работает хорошо, как и tmp
является идентификатором связанным let
. Если же я пытаюсь сделать p
псевдоним для переменного шаблона tmp
связанных with-syntax
, то он не работает, как ожидалось:
#lang racket
(require racket/stxparam)
(define-syntax-parameter p #f)
(define-syntax (test-2-p stx)
(syntax-case stx()
[(_ body)
#'(with-syntax ([tmp #'(foo 123)])
(syntax-parameterize ([p (make-rename-transformer #'tmp)])
body))]))
(test-2-p #'p) ;; gives #'p, instead of #'(foo 123)
Если вместо этого я объявляю синтаксис p-unhygienic
, и привязать его к (make-rename-transformer #'tmp)
, то это работает штраф:
#lang racket
(define-syntax (test-3-p stx)
(syntax-case stx()
[(_ body)
#`(with-syntax ([tmp #'(foo 123)])
(define-syntax #,(syntax-local-introduce #'p-unhygienic)
(make-rename-transformer #'tmp))
body)]))
(test-3-p #'p-unhygienic) ;; gives #'(foo 123), as expected
Как я могу создать гигиенический псевдоним для переменного шаблона с помощью syntax-parameterize
?
Это не ошибка, хотя это * * является ограничением. В документации для 'syntax-parameterize' указано, что« Если 'expr' создает результат« make-rename-transformer », тогда' id' может использоваться как макрос, который расширяется до использования целевого идентификатора, но 'syntax- local-value' 'id' не дает значения цели.« Я не совсем уверен, почему это ограничение существует, но было бы интересно найти объяснение. В статье о синтаксических параметрах, похоже, не упоминается. Я предполагаю, что сами параметры синтаксиса используют косвенное отношение, которое делает их несовместимыми с «синтаксисом-локальным значением» напрямую. –
В этом случае было бы задачей 'синтаксиса 'просматривать синтаксические параметры так же, как и через переименовать-трансформаторы? –
Я так не думаю. Лично, если это что-то трудное, чтобы справиться с этим правильно, я бы подумал, что это будет «синтаксис-локальный-значение», так как в противном случае каждый макрос, который использует «синтаксис-локальное значение», должен также добавить специальную обработку для параметров синтаксиса. Конечно, из-за того, как параметры синтаксиса реализованы в Racket, тогда как «синтаксис-локальный-значение» реализован на C, это может быть сложным, но похоже, что здесь нужно улучшить сотрудничество. –