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
由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
爲模式變量創建一個衛生別名?
這不是錯誤,但它是* *的限制。 'syntax-parameterize'的文檔聲明「如果'expr'產生一個'make-rename-transformer'結果,那麼'id'可以被用作一個擴展爲使用目標標識符的宏,但'syntax- 'id'的local-value'不會產生目標值。「我不完全確定這個限制存在的原因,但找到解釋會很有趣。關於語法參數的論文似乎沒有提到它。我的猜測是,語法參數本身使用一種間接性,使它們直接與'syntax-local-value'不兼容。 –
在這種情況下,它會是'語法'的工作來查看語法參數,就像通過重命名變換器一樣? –
我不這麼認爲。就個人而言,如果正確處理這件事情的任何工作,我會認爲它是'syntax-local-value',否則每個使用'syntax-local-value'的宏都需要爲語法參數添加特殊處理。當然,由於語法參數在Racket中的實現方式,而在C中實現'syntax-local-value',這可能很複雜,但似乎需要在這裏進行更好的合作。 –