2010-08-15 43 views
8

一些人聲稱LISP中的單個命名空間會導致不衛生的宏。 http://community.schemewiki.org/?hygiene-versus-gensym導致不衛生宏的單個命名空間是什麼? (在LISP中)

http://www.nhplace.com/kent/Papers/Technical-Issues.html

什麼恰恰是它關於有單,雙或多個命名空間,導致宏觀衛生?

+1

由於您在三個小時以後沒有收到任何(真實)答案:您可以嘗試在「Lambda the Ultimate」上提問。你可能會被踢出去,因爲這個列表實際上是關於編程語言的研究,但那裏的人肯定能回答你的問題。 http://lambda-the-ultimate.org/ – Eike 2010-08-15 16:40:22

回答

7

Lisp-2意味着你有兩個命名空間:一個用於功能,一個用於其他的東西。

這意味着你不太可能在不知不覺中重新綁定宏中的函數值(或var值)。

在Lisp-1中,由於存在一個命名空間,因此您(在統計上但不是實際上)命中現有定義的概率是其兩倍。

實際上,Lisp-1s的衛生已經涵蓋了像gensym這樣的東西,而Scheme的易混淆廣泛的syntax-structure類似於讓衛生保持衛生的宏。

盡我所知,這個問題大多是一個稻草人的論點:它只是在較差或較舊的實現中的問題。

Clojure通過gensym或閱讀器宏myvar##本質上爲gensym)提供了衛生宏。

而且你不必擔心本地範圍在您的宏重新綁定你的函數,或者:Clojure是所有清潔:

user=> (defmacro rev [xs] `(reverse ~xs)) 
#'user/rev 
user=> (rev [1 2 3]) 
(3 2 1) 
user=> (let [reverse sort] (rev [1 2 5 3 6])) 
(6 3 5 2 1) 

而且這裏的一些變量衛生:

user=> (defmacro k [] (let [x# "n"] x#)) 
#'user/k 
user=> (k) 
"n" 
user=> (let [x "l"] (k)) 
"n" 
user=> (let [x "l"] (str (k) x)) 
"nl" 

公告我們的性感gensym'd x#

+4

其實'rev'宏的工作原理主要是因爲Clojure如何自動解析由文法中引入的符號 - 引用形式,以及名稱空間限定符號可能未命名('reverse'實際上變成擴展中的'clojure.core/reverse';'(let [reverse:foo](rev ...))'不是問題,因爲'rev'表單的擴展從不提及'反向「 - 它提到'clojure.core/reverse')。就我所知,這是Clojure對宏觀衛生辯論的一項創新貢獻。 – 2010-08-16 00:26:49

+3

當然'gensym'在這裏是非常重要的,但是一個包裝系統(包裝是CL lingo;這就是Clojure土地使用的「名稱空間」這個詞)對於非衛生的宏觀健康也是至關重要的,而Clojure的自動解決方法是這是一種特別聰明的方式,儘可能地幫助它。 – 2010-08-16 00:29:12

+2

我完全忘了語法引用完全解決了它所包含的符號:謝謝你!我想我的回答是正確的,但這是一個重要/有趣的事情要注意。我在這個問題的答案的早期迭代中實際上利用了這一點:http://stackoverflow.com/questions/3480377/clojure-namespace-management-is-there-a-way-to-save-and-restore -cl-of-state-of-cl 再次感謝米哈爾爲清理事情。 – Isaac 2010-08-16 00:51:07