2016-08-30 69 views
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結合的標識符。但是,如果我試圖讓pwith-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爲模式變量創建一個衛生別名?

回答

2

這是一個有趣的案例,我期待你做同樣的事情。這可能是某處或某處的缺陷;我不確定。無論採用哪種方式,都提供了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)> 
+1

這不是錯誤,但它是* *的限制。 'syntax-parameterize'的文檔聲明「如果'expr'產生一個'make-rename-transformer'結果,那麼'id'可以被用作一個擴展爲使用目標標識符的宏,但'syntax- 'id'的local-value'不會產生目標值。「我不完全確定這個限制存在的原因,但找到解釋會很有趣。關於語法參數的論文似乎沒有提到它。我的猜測是,語法參數本身使用一種間接性,使它們直接與'syntax-local-value'不兼容。 –

+0

在這種情況下,它會是'語法'的工作來查看語法參數,就像通過重命名變換器一樣? –

+0

我不這麼認爲。就個人而言,如果正確處理這件事情的任何工作,我會認爲它是'syntax-local-value',否則每個使用'syntax-local-value'的宏都需要爲語法參數添加特殊處理。當然,由於語法參數在Racket中的實現方式,而在C中實現'syntax-local-value',這可能很複雜,但似乎需要在這裏進行更好的合作。 –