I am trying to write a clojure macro that transforms clojure keywords to java enums. But the evaluation of the parameters in a macro is confusing:
user=> (defmacro show-and-tell [thing]
#_=> `(vector ~(name thing) ~(type thing) ~thing))
#'user/show-and-tell
user=> (macroexpand-1 (show-and-tell :foo))
["foo" clojure.lang.Keyword :foo]
user=> (def foo :bar)
#'user/foo
user=> (name foo)
"bar"
user=> (type foo)
clojure.lang.Keyword
user=> (macroexpand-1 (show-and-tell foo))
["foo" clojure.lang.Symbol :bar]
So it works as I would expect if the keyword is provided directly as a parameter. But if it is a var, I don't get the correct name and type of the thingy.
I can make it 'sort-of-almost' work by using eval:
user=> (defmacro show-and-tell-with-eval [thing]
#_=> `(vector ~(name (eval thing)) ~(type (eval thing)) ~(eval thing)))
#'user/show-and-tell-with-eval
user=> (macroexpand-1 '(show-and-tell-with-eval foo))
(clojure.core/vector "bar" clojure.lang.Keyword :bar)
user=> (let [baz :bar-foo] (macroexpand-1 '(show-and-tell baz)))
(clojure.core/vector "baz" clojure.lang.Symbol baz)
user=> (let [baz :bar-foo] (macroexpand-1 '(show-and-tell-with-eval baz)))
CompilerException java.lang.RuntimeException: Unable to resolve symbol: baz in this context
Can someone explain this to me? Is there no way to see the name of a (local) var inside a macro?