views:

54

answers:

1

I'm a little confused by how keyword accesses seem to behave in Clojure when they are evaluated at macro expansion time.

The following works as I expect:

(def m {:a 1})
(:a m)
=> 1 

However the same keyword access doesn't seem to work within a macro:

(def m {:a 1})
(defmacro get-a [x] (:a x))
(get-a m)
=> nil

Any idea what is going on here?

+7  A: 

You should take into account that macro's don't evaluate their arguments, unless you tell them so. In your version, get-a gets a symbol m and the result isn't code, it is keyword :a looking itself up in a symbol, which is obviously nil. This works however:

(defmacro get-a [x] `(:a ~x))

The result of calling this macro with argument m is the expression '(:a m)', which evaluates to 1 in your context.

Michiel Borkent
OK - so if you want to have the macro expand to just "1" rather than "(:a m)" how would you do that? I'm interested in how you get the keyword lookup to happen at macro expansion time rather than later if that makes sense.....
mikera
If you really want to do that, you can use eval:(defmacro get-a [x] (:a (eval x))), but if that is all you need, a function is way more appropriate here.
Michiel Borkent
Cool - that works perfectly! Many thanks! Seems like what I needed to do was evaluate the symbol. I'm actually trying to do something much more complicated with macros but this particular behaviour was tripping me up :-)
mikera