2011-03-26 106 views
7

我在構建Clojure中的DSL時遇到了問題。這是我從其他一切中分離出來的具體問題。宏的Clojure評估

比方說,我們哈瓦一個簡單的宏:

user> (defmacro m1 [x] `'~x) 
#'user/m1 

它只是返回字面提供 用戶>(M1 toUpperCase) toUpperCase

如果我們呼籲對象的一切Java方法按預期工作

user> (. "a" toUpperCase) 
"A" 

但是如果我們用方法名替代宏調用返回方法名

user> (. "a" (m1 toUpperCase)) 

; Evaluation aborted. 
Unable to resolve symbol: toUpperCase in this context 

我想使用一些具有流暢接口像a()。b()。c()的java庫。 它映射到的Clojure爲:

(.. obj method1 method2 method3....etc) 

我想創建一個替代這條產業鏈的某些部分的宏,所以我的代碼應該是這樣的:

(.. obj method1 macro1) 

,並應擴大到

(.. obj method1 method2 method3) 

definline也沒有幫助。我也試過

回答

6

你遇到這個問題的原因是。特殊形式不會按照您期望的方式評估其第二個參數(指定方法或字段的符號):它將其視爲METHOD m1的調用,並將其與ARUUMENT toUppercase進行比較。因此,不能動態地爲方法生成符號,只能作爲參數。 (點) - 即使您使用宏來指定該參數。

解決此問題的一種方法是包括。在您的宏:

(defmacro m1 [x y] `(. ~x (~y))) 
(m1 "a" toUppercase) 
user> "A" 

請注意,您需要環繞〜Ÿ括號來表示你要調用的方法,而不是讀的字段。

+0

非常感謝!這是很好的建議。 – 2011-03-28 06:50:55