The syntax-parameterize
is commonly used in conjunction with make-rename-transformer
so that the syntax-parameter p
behaves as an alias for another identifier:
#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
The code above works well, as tmp
is an identifier bound by let
. If however I try to make p
an alias for the pattern variable tmp
bound by with-syntax
, then it does not work as expected:
#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)
If instead I declare a p-unhygienic
syntax, and bind it to (make-rename-transformer #'tmp)
, then it works fine:
#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
How can I create a hygienic alias for a pattern variable using syntax-parameterize
?
This is an interesting case, I expected the same thing you did. This might be either a bug somewhere or a limitation; I'm not sure. Either way, the define-rename-transformer-parameter
form is provided as a workaround.
The initial value of a rename-transformer-parameter must be a rename-transformer, so you can use a p-init
identifier with #f
as the transformer binding.
(define-syntax p-init #f)
(define-rename-transformer-parameter p (make-rename-transformer #'p-init))
In context:
#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)>