2012-01-11 96 views
2

正如另一篇文章寫的,我正在Clojure編寫一個沉編譯器。 對於我需要一個宏/功能,其接收符號作爲參數,並且如果沉功能被綁定到其它返回功能,並且如果該符號被定義爲Clojure的宏它應該返回宏,所以((function or) true false)應該給出相同的結果如(or true false)從Clojure的宏返回宏

我的宏目前的樣子:

(defmacro kl/function [x] 
(cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))] 
    (if (function? fn) `(eval ~fn) `(quote ~x)))) 

的「__fnPoF__」後綴是因爲在沉雙命名空間的存在。 (A值和功能可分配到相同的符號。)現在

我的問題是((function or) true false)計算結果爲假,因爲它的計算結果爲('or true false)但是如果我離開了,而不是`(quote ~x)「引用」(x我得到的以下情況除外:

kl=> (function *) 
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'kl/*, compiling:(NO_SOURCE_PATH:8) 

是否有人有一個想法如何解決這個問題

回答

3

你不能「迴歸」的宏,因爲宏沒有任何價值,但你可以讓(函數或)擴大?符號或;然後通常的Clojure宏展開/評估機制w生病只是你想要的。所以,雖然我不知道沉是如何工作的,這似乎是一個簡單的變化將是:

(defmacro kl/function [x] 
    (cl/let [fn (symbol (cl/str (name x) "__fnPoF__"))] 
    (if (function? fn) 
     `(eval ~fn) 
     x))) 

順便說一句,這eval在我看來是一個災難等待發生。我強烈懷疑eval對於你的目標是必要的。

+0

正如我上面寫的,如果我取代''(報價X)''通過我x'得到'CompilerException了java.lang.RuntimeException:無法採取的宏觀值:#'KL/*,編譯:(NO_SOURCE_PATH:8)' – 2012-01-12 08:49:09

+0

@NameLess哇,這很有趣。它看起來像宏展開器看到'((function when)...)'沒有宏作爲它的第一個子表單,所以它放棄了宏展開。然後,當內在事物擴展到「時間」時,它不會恢復。我不知道你會如何處理這個問題。 – amalloy 2012-01-12 18:08:10