2013-06-20 33 views
2

我對宏很新,所以我有一個基本的問題似乎與Java對象在Clojure代碼中表示的方式。我應該返回一個地圖宏:clojure宏問題與Java對象返回地圖

(defmacro g [] 
    (let [m {:color :black}] 
    `(identity ~m))) 


user=> (g) 
{:color :black} 

然而,當我在地圖上使用Java對象時,事情就變得怪異

(defmacro g [] 
    (let [m {:color java.awt.Color/BLACK}] 
    `(identity ~m))) 

user=> (g) 
CompilerException java.lang.RuntimeException: Can't embed object in code, maybe 
print-dup not defined: java.awt.Color[r=0,g=0,b=0], compiling:(NO_SOURCE_PATH:1 
:1) 

如果我改變defmacrodefn輸出看起來是這樣的:

user=> (g) 
(clojure.core/identity {:color #<Color java.awt.Color[r=0,g=0,b=0]>}) 

所以我猜這個表示法正在讓讀者知道。有沒有一個正確的方法來做到這一點?

回答

0

有幾種方法可以通過一種方式來編寫這種方式,因爲適當的方法是讓宏返回一個表單,其中包括let

user> (defmacro g [] 
      `(let [m# {:color java.awt.Color/BLACK}] 
       (identity m#))) 
#'user/g 
user> (g) 
{:color #<Color java.awt.Color[r=0,g=0,b=0]>} 

這允許從類中解析對象。

+0

從對名稱空間的意義上來說,當對象「解析」時,這不會改變:解析全部在讀取時完成,在宏定義的名稱空間中完成。不同之處在於宏,而不是以某種神奇的方式*包括*「黑色」,就像我在源代碼中輸入黑色的想法一樣,產生的代碼在類中查找「BLACK」作爲靜態字段運行時java.awt.Color'。 – amalloy

+0

謝謝,我得到了完全錯誤*腮紅*固定。 –

0

這是您的宏展開時發生的情況。

(macroexpand '(g)) 
;=> (clojure.core/identity {:color #<Color java.awt.Color[r=0,g=0,b=0]>}) 

請注意Java對象是不是可讀形式?

+0

我不確定編譯器是否打印並重新讀取評估週期之間的表單? –

+0

爲什麼這會失敗? (我很好奇。)錯誤消息提到'print-dup'可能沒有爲對象定義。 – Jeremy

+0

嗯,我爲'java.awt.Color'實現了'print-dup',並且它在打印擴展宏時似乎沒有使用它。 – Jeremy