2

通常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的模式变量创建别名,则它不会按预期工作:tmpwith-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

4

1 回答 1

2

这是一个有趣的案例,我期待你做同样的事情。这可能是某个地方的错误或限制;我不确定。无论哪种方式,该define-rename-transformer-parameter表单都是作为一种解决方法提供的。

rename-transformer-parameter 的初始值必须是 rename-transformer,因此您可以使用p-init标识符 with#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)>
于 2016-08-30T18:46:13.423 回答