2014-09-23 48 views
5

Freenode的#scheme頻道詢問了一個很好的問題。請看下面的代碼方案:計劃中的宏和內部定義

(define alpha 1) 

(define-syntax foo 
    (syntax-rules (quote alpha) 
    ((_ alpha msg) (define bar 2)) 
    ((_ other msg) (syntax-error msg)))) 

(define (beta) 
    (foo alpha "beta") 
    (define alpha 3) 
    'beta) 

(define (gamma) 
    (define alpha 4) 
    (foo alpha "gamma") 
    'gamma) 

(define (delta alpha) 
    (foo alpha "delta") 
    'delta) 

哪個betagammadelta應該產生語法錯誤的嗎?而哪個?我已經用赤壁計劃檢查了這個,其中beta很好,而gammadelta失敗。我想知道這是一個有意的行爲還是僅僅是赤壁的一個bug。

根據該標準,在內部定義被重寫爲letrec*之前,擴展宏似乎應該發生。因此betagamma都應該都失敗,因爲foo將與內部定義的alpha匹配,而不是全局匹配。

但是,沒有明確的標準規定內部定義是如何工作的,只是他們可以被作爲letrec快捷想到的。我使用Racket的R5RS獲得了相同的行爲,所以看起來我錯過了標準中要求這種行爲的東西。

+0

在R6RS(基於psyntax的impl)中,調用過程時我得到相同的行爲。 – leppie 2014-09-26 07:40:54

回答

1

好吧,我終於明白你的問題。運行你的代碼是有挑戰性的,因爲你似乎有一個'語法錯誤'函數,只有在完全展開的代碼中才會發出語法錯誤。隨你。

我想回答你的問題是這樣的:

這些計劃傢伙(Dybvig,Felleisen,Hieb,克林格,里斯,魔杖,弗拉特,卡爾佩珀等),是相當聰明!

特別是,不知何故Scheme/Racket能夠找出綁定結構是如何工作的,即使它不知道綁定是否是綁定。你是對的!太瘋狂了!但是Dybvig等人提出的算法。做一些非常聰明的事情,以確保衛生跟蹤標識符是否「自由標識符相等」或「綁定標識符相等」(弗拉特的術語),即使它還不知道哪一個綁定另一個。我個人建議閱讀「共同工作的宏」(Flatt,Culpepper,Darais,Findler)以更好地理解這一點。

道歉,如果我誤解了你的問題,或者我的語氣不合適!

1

取決於實現方面可能有點太多,但這種行爲是因爲宏擴展的順序。從理論上講,所有定義都包含alpha,因此它不應與字面關鍵字中的定義相匹配。但是,在將define表單擴展爲letrec*之前,需要先進行宏擴展,否則編譯器無法正確檢測到內部定義。所以在那個時候,編譯器可能會看到綁定,也可能看不到綁定。 (宏展開時間是指定的R7RS ,因此實現可以選擇自己的時間也是如此。)

對於beta情況下,編譯器沒趕上綁定,宏觀擴張仍然可以看到alpha是相同的具有全球約束力。其他情況是相反的。

0

首先,delta超出(應該不匹配alpha),因爲它清楚地詞法結合alpha比相互結合下,你的sytnax-rules出現。有趣的是betagamma

根據第5.2.2節。 R4RS(第13頁)和R5RS(第16頁)第5.3.2節。 R7RS(第26頁)和第11.3節。的R6RS(第32頁),通過內部定義建立的結合的「區域」是整個<body>,其中定義出現在。並且您的對foo的宏調用顯然與那些內部定義相同<body>

R7RS也又進了一步,並警告我們:

需要注意的是這樣一個機構[即一個包含內部定義]在擴展其他語法之前可能不明顯。

所以事件的混亂順序被承認,但沒有歧義;如果與alpha的分支綁定的位置與調用宏時相同的<body>中的任何內部定義不匹配,則syntax-rules應該與alpha分支不匹配。 因此,betagamma也出來了。

附錄A

如果我們使情況更加複雜,並且您的宏自身條件的約束alpha,像

(syntax-rules (alpha) 
    ((_ alpha x) (define alpha x))) 

的話,好像在首先想到真正的曖昧,但我相信這是通過這樣一個事實解決了這個事實:宏擴展器將根據衛生重新命名定義的alpha標識符,這意味着我們不會將我們正在匹配的alpha映射爲文字,因此匹配它很好,並且th上面的e將簡單地創建一個在宏體外部無法訪問的重命名的alpha的綁定。

附錄B

有一個在5.3節的端部的約束。的R5RS(第17頁),第5.4節結尾。 (第26頁)和第10部分的中間部分。在R6RS(第30頁)中,提到的定義序列不應包含改變其中任何一個的含義的定義。 (這實際上是一個有點複雜,使用這三種標準的不同寫法,但應該是一個合理的摘要。)

在您的例子,它是我不清楚你syntax-rules的可能性是否擴大到語法錯誤計數作爲其「含義」的模糊性。如果有人認爲它是模糊的,那麼您的betagamma是按照R5RS和R7RS的「錯誤」(未定義的行爲),以及按照R6RS的「違反語法」。

如果您的示例在syntax-rules的第二個分支中包含另一個綁定(理想情況下甚至是同一個變量的定義),那麼這個挑選將不適用,因此您的問題仍然存在。