2014-09-13 60 views
3

我正在探索Scheme宏,但是我一直無法找到一個寫便利宏的方法。如何在便攜式方案中編寫照應宏?

我試圖寫一個each-it宏,使得該代碼:

(each-it (list 1 2 3) 
    (display it)) 

擴展到這一點:

(for-each (lambda (it) 
      (display it)) 
      (list 1 2 3)) 

我寫了一個宏觀與syntax-rules,但是這給了我當我嘗試使用它時出現關於未定義標識符的錯誤。

(define-syntax each-it 
    (syntax-rules() 
    ((each-it lst body) 
    (for-each (lambda (it) body) 
       lst)))) 

This SO question提到define-syntax-parameter,這似乎是唯一的球拍。 This blog post給出了一些Scheme代碼示例,但代碼示例不在R5RS模式下的DrRacket中運行(我認爲它是方括號?)。

R4RS has an interesting macro appendix但它不存在於R5RS中,我不知道我是否可以依賴它。

我可以用完全便攜的方式編寫我的each-it宏嗎?如果不是,寫宏的最常用的宏系統功能是什麼?

+0

R5RS http://people.csail.mit.edu/jaffer/r5rs_6.html#SEC39 – Rptx 2014-09-13 17:34:22

+0

@Rptx中有一段宏,但我看不到任何設備在該部分破壞衛生。 – 2014-09-13 22:16:10

+0

簡單的解決辦法就是[保持衛生](http://community.schemewiki.org/?anaphoric-if)。 – Sylwester 2014-09-14 00:34:35

回答

4

這應該是便攜式的,至少在R6RS:

(define-syntax each-it 
    (lambda (x) 
    (syntax-case x() 
     ((_ lst body) 
     (with-syntax ((it (datum->syntax x 'it))) 
     #'(for-each (lambda (it) body) lst)))))) 
3

是的,你可以把它寫在便攜方式假設R6RS是對你不夠便攜。 (在R7RS上也是如此,目前只有syntax-rules,但不清楚大型語言中包含什麼,或者何時會發生。)請參閱uselpa's來了解如何做到這一點。

那麼我爲什麼要寫另一個答案?因爲實際上這樣做會是一個糟糕的主意。一個不好的主意不是在某種模糊的學術意義上,對於大多數現實世界的代碼來說都沒有關係 - 從某種意義上講,這很可能會在以後出現。我知道「紙」使它看起來很嚇人,但至少讀了你見過的另一個SO問題中提到的the paper的前兩部分。具體來說,第1.2部分顯示了您將遇到的問題。然後,第2部分展示瞭如何「正確地」完成此操作,以便編寫可擴展到使用宏的宏。在這一點上,採取「保持衛生」的方式會很有吸引力,但在第二部分結束時,你會明白爲什麼這樣做不起作用。

IMO的底線是,除非你有語法參數或類似的東西,否則就不要這樣做。也許唯一的例外(可能是你的情況)是當宏是你打算使用自己的東西時,你永遠不會把它提供給其他人。

+0

謝謝,這篇論文是對Scheme中衛生學的一個夢幻般的概述。 – 2014-09-14 12:24:32