2012-06-02 39 views

回答

3

使用#'(即syntax)時,你是不是構建一個新的語法對象,因爲當你只是引用與syntax-casewith-syntax結合的模式變量。

使用#'作爲臨時語法對象,如(syntax->list #'(id ...))

使用#'表示語法對象,這些語法對象表示您知道其中沒有語法錯誤的語法對象,或者其中的語法錯誤是宏實現的錯誤,而不是宏的使用。

使用syntax/loc當您構造表達式時,由於錯誤地使用了宏,可能會包含語法錯誤。

讓我們考慮一個具體的例子:

形式display-let應該工作完全像正常let,除了它是評估主體之前顯示綁定的值。

這是第一個實現:

(define-syntax (display-let-1 stx) 
    (syntax-case stx() 
    [(_ ([id expr] ...) body ...) 
    #'((lambda (id ...) 
      (displayln (format "~a is bound to ~a" 'id id)) ... 
      body ...) 
     expr ...)])) 

這是一個正確的使用宏的例子:

> (display-let-1 ([x 1] [y 2]) (+ x y)) 
x is bound to 1 
y is bound to 2 
3 

現在讓我們看看會發生什麼當宏使用不當:

> (display-let-1()) 
lambda: bad syntax in: (lambda()) 

此用法不正確,因爲使用let必須始終有一個空的身體。除了打印錯誤消息,DrRacket顏色此代碼紅色:

(lambda (id ...) 
    (displayln (format "~a is bound to ~a" 'id id)) ... 
    body ...) 

雖然是正確的,由宏構建的lambda表達不正確,(lambda())是不合法的,它不是由於錯誤的宏,但由於宏的使用不正確。

要將指定的lambda表達式與syntax/loc重新定向,請使用syntax/loc的第一個參數作爲紅色的位置。

(define-syntax (display-let-2 stx) 
    (syntax-case stx() 
    [(display-let ([id expr] ...) body ...) 
    #`(#,(syntax/loc stx (lambda (id ...) body ...)) expr ...)])) 

> (display-let-2()) 
display-let-2: bad syntax in: (display-let-2()) 

這次在REPL進入(display-let-2())周圍是紅色,並且錯誤消息中提到display-let-2而不是lambda

相關問題