2

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?

2 Answers 2

0

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.

1
  • This doesn't change when the object is "resolved", in the sense of namespaces: the resolution is all done at read-time, in the namespace in which the macro is defined. The difference is that the macro, rather than in some magical way including "the color black" as though I had typed the idea of blackness in as source code, produces code that looks up BLACK as a static field in the class java.awt.Color at runtime.
    – amalloy
    Commented Jun 20, 2013 at 20:08
0

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?

3
  • I'm not sure the compiler prints and re-reads the forms between cycles of evaluation? Commented Jun 20, 2013 at 18:57
  • Why else would this fail? (I'm curious.) The error messages mentions that print-dup may not be defined for the object.
    – Jeremy
    Commented Jun 20, 2013 at 19:05
  • Hmm, well I implemented print-dup for java.awt.Color and it doesn't appear to use it when printing the expanded macro.
    – Jeremy
    Commented Jun 20, 2013 at 19:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.