0

I'm passing my macro to a map operation. I'm having some trouble getting my values out. Here is an example:

(def num-vec [1 2 3 4 5])

(defmacro describe-args [first-arg]
  `(println '~first-arg " = " ~first-arg))

(doall (map #(describe-args (+ 42 %)) num-vec))

This returns:

(+ 42 p1__437#)  =  43
(+ 42 p1__437#)  =  44
(+ 42 p1__437#)  =  45
(+ 42 p1__437#)  =  46
(+ 42 p1__437#)  =  47

My question is: How do I get the nested argument in a macro inside a mapped function in Clojure?

(I believe this is a different question to the other map/macro questions already asked as this is about nested argument retrieval).

hawkeye
  • 34,745
  • 30
  • 150
  • 304

1 Answers1

3

Macros expand at compile time.

(doall (map #(describe-args (+ 42 %)) num-vec))

gets expanded to something like:

(doall (map (fn [tmpvarname] 
              (describe-args (+ 42 tmpvarname))
            num-vec))

tmpvarname is unique and will change each time the macro is expanded. Then the code gets further expanded:

(doall (map (fn [tmpvarname] 
              (println '(+ 42 tmpvarname) " = " (+ 42 tmpvarname))) 
            num-vec))

This gets done before the code gets executed and the macro expander doesn't know what num-vec is other than being a variable symbol. Actually it won't know what map or println is either since at the macro expansion time the code is data. map is just a symbol.

Now when this code is run the runtime need not know there ever was a macro there to begin with. When map does its thing there are no macros.

Macros change code before it is run. Its purpose is to reduce complexity and code size but it adds some confusion since the programmer who reads code needs to learn what is a custom macro in the code base she is reading. Paul Graham suggests in On Lisp that you might have to use the macro ten or twenty times before it yields a net improvement in readability.

amalloy
  • 89,153
  • 8
  • 140
  • 205
Sylwester
  • 47,942
  • 4
  • 47
  • 79
  • Really appreciate your answer. Could you clarify what the difference is to this situation? http://stackoverflow.com/questions/28539818/how-do-i-get-the-argument-in-a-macro-from-a-map-macro-in-clojure (ie non-nested arguments to a macro in a map) – hawkeye Feb 21 '15 at 20:53