I'm very new to macros so I have a basic question that seems to do with the way that Java objects are represented in Clojure code. I have a macro that should return a map:
(defmacro g []
(let [m {:color :black}]
`(identity ~m)))
user=> (g)
{:color :black}
However when I use a java object in the map, things get weird
(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)
If I change defmacro
to defn
the output looks like this:
user=> (g)
(clojure.core/identity {:color #<Color java.awt.Color[r=0,g=0,b=0]>})
So I'm guessing the representation is borking up the reader. Is there a correct way to do this?
There are several ways to write this though one way that strikes me as appropriately macro-ish is to have it return a form that evaluates to the map including the 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]>}
This allows the object to be resolved from the class.