Параметр синтаксиса, указывающий на переменную шаблона синтаксиса?

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?

1 ответ

Решение

Это интересный случай, я ожидал того же, что и вы. Это может быть либо ошибка, либо ограничение; Я не уверен. В любом случае, define-rename-transformer-parameter Форма предоставляется в качестве обходного пути.

Начальным значением параметра rename-transformer-должен быть rename-transformer, так что вы можете использовать p-init идентификатор с #f в качестве трансформаторной привязки.

(define-syntax p-init #f)
(define-rename-transformer-parameter p (make-rename-transformer #'p-init))

В контексте:

#lang racket

(require racket/stxparam)
(define-syntax p-init #f)
(define-rename-transformer-parameter p (make-rename-transformer #'p-init))

(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) ; #<syntax:10:28 (foo 123)>
Другие вопросы по тегам