Macros clojure宏返回带有java对象的映射时出现问题
我对宏非常陌生,所以我有一个基本问题,似乎与Clojure代码中表示Java对象的方式有关。我有一个宏,它应该返回一个映射:Macros clojure宏返回带有java对象的映射时出现问题,macros,clojure,clojure-java-interop,Macros,Clojure,Clojure Java Interop,我对宏非常陌生,所以我有一个基本问题,似乎与Clojure代码中表示Java对象的方式有关。我有一个宏,它应该返回一个映射: (defmacro g [] (let [m {:color :black}] `(identity ~m))) user=> (g) {:color :black} 然而,当我在地图中使用java对象时,事情变得很奇怪 (defmacro g [] (let [m {:color java.awt.Color/BLACK}] `(
(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)
如果我将defmacro
更改为defn
,则输出如下所示:
user=> (g)
(clojure.core/identity {:color #<Color java.awt.Color[r=0,g=0,b=0]>})
user=>(g)
(clojure.core/identity{:color})
所以我猜这种表现会让读者感到厌烦。有没有正确的方法可以这样做?有几种方法可以这样写,但我觉得有一种方法是让它返回一个表单,该表单的计算结果是映射,包括
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]>}
user>(定义宏[]
`(让[m#{:color java.awt.color/BLACK}]
(身份m#))
#'用户/g
用户>(g)
{:颜色#}
这允许从类解析对象。这是宏展开时发生的情况
(macroexpand '(g))
;=> (clojure.core/identity {:color #<Color java.awt.Color[r=0,g=0,b=0]>})
(宏扩展(g))
;=> (clojure.core/identity{:color})
注意Java对象的可读性如何?我不确定编译器是否在计算周期之间打印并重新读取表单?否则为什么会失败?(我很好奇。)错误消息提到可能没有为对象定义
print dup
。嗯,我为java.awt.Color
实现了print dup
,并且在打印扩展宏时似乎没有使用它。当对象“解析”时,这不会改变,在名称空间的意义上:解析都是在读取时在定义宏的名称空间中完成的。不同之处在于,宏不是以某种神奇的方式包括“黑色”,就像我在源代码中键入了黑色的概念一样,而是在运行时将black
作为类java.awt.color
中的静态字段进行查找。