On Jan 1, 2009, at 5:45 AM, synphonix wrote:
> > Hello and happy new year, > > I've started this year with playing around with clojure macros and > wrote a macro that > behaves in a way I don't understand: > > (defmacro foo > ([x] `(list ~x ~x)) > ([x n] (if (<= n 0) > `(foo ~x) > `(foo ~(foo x) > ~(- n 1))))) > > (foo :a 0) => (:a :a) ;; What I expected > (foo :a 1) => nil ;; Here I would expect (foo (foo :a) 0) => (foo > (list :a :a) 0) => '((:a :a) (:a :a)) > (foo :a 2) => java.lang.NullPointerException > > Could someone please explain where my understanding of clojure macros > is flawed ? > Yes, as is so often the case, macroexpand(-1) can illuminate: Your problem is that when you say ~(foo x) you are running the macro during its own definition, rather than expanding into a call to itself: (macroexpand-1 '(foo :a 1)) -> (user/foo (:a :a) 0) ;oops What you want instead is to emit a call to the same macro in the expansion, ~(foo x) changed to (foo ~x): (defmacro foo ([x] `(list ~x ~x)) ([x n] (if (<= n 0) `(foo ~x) `(foo (foo ~x) ~(- n 1))))) (macroexpand-1 '(foo :a 1)) -> (user/foo (user/foo :a) 0) (macroexpand '(foo :a 1)) -> (clojure.core/list (user/foo :a) (user/foo :a)) (foo :a 1) -> ((:a :a) (:a :a)) (foo :a 2) -> (((:a :a) (:a :a)) ((:a :a) (:a :a))) Rich --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---