指向语法模式变量的语法参数?
syntax-parameter pointing to a syntax-pattern-variable?
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
成为由 with-syntax
绑定的模式变量 tmp
的别名,那么它不会按预期工作:
#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
为模式变量创建卫生别名?
这是一个有趣的案例,我预计你会做同样的事情。这可能是某处的错误或限制;我不确定。无论哪种方式,define-rename-transformer-parameter
表单都作为解决方法提供。
重命名转换器参数的初始值必须是重命名转换器,因此您可以使用 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)>
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
成为由 with-syntax
绑定的模式变量 tmp
的别名,那么它不会按预期工作:
#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
为模式变量创建卫生别名?
这是一个有趣的案例,我预计你会做同样的事情。这可能是某处的错误或限制;我不确定。无论哪种方式,define-rename-transformer-parameter
表单都作为解决方法提供。
重命名转换器参数的初始值必须是重命名转换器,因此您可以使用 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)>