2

我对宏很陌生,所以我有一个基本问题,似乎与 Java 对象在 Clojure 代码中的表示方式有关。我有一个应该返回地图的宏:

(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]>})

所以我猜这种表示会让读者感到厌烦。有没有正确的方法来做到这一点?

4

2 回答 2

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]>}

这允许从类中解析对象。

于 2013-06-20T18:48:41.010 回答
0

这就是扩展宏时发生的情况。

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

请注意 Java 对象如何不是可读形式?

于 2013-06-20T18:52:15.933 回答