Pergunta

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?

Foi útil?

Solução

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.

Outras dicas

This is what happens when your macro is expanded.

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

Notice how the Java object is not in a readable form?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top