Looping through args of macro
Asked Answered
E

1

6

I am trying to write a macro in Clojure that allows for evaluation of a series of simple "def" expressions. I am a n00b when it comes to macros. The idea is that

(my-defs y1 1
     y2 "taco")

should expand to

(do (def y1 1) (def y2 "taco"))

The following code accomplishes this for the special case of two defs

(defmacro my-defs 
  [& args]
  `(do
     (def ~(first args) ~(second args))
     (def ~(nth args 2) ~(nth args 3) )))

which is nice, but I am having trouble generalizing this. I tried out a few naive things involving looping through bindings of the elements of (partition 2 args) but I always got garbage (I know this isn't very specific but the diversity and extent of the garbage seemed a bit too much to report here). How do I loop over these are and evaluate my defs?

P.S. The macro my-defs is a toy. What i really want to accomplish in the end is a littel helper macro to instantiate a bunch of multimethod instances. Currently I have large chunks of code that look like

(defmethod f [A B] [x] "AB")
(defmethod f [A A] [x] "AA")
(defmethod f [C B] [x] "CB")

which is a little unsightly. It would be nice if I could do something like

(defmethods f
  [A B] [x] "AB"
  [A A] [x] "AA"
  [C B] [x] "CB")

instead.

Ecumenism answered 5/9, 2011 at 22:7 Comment(0)
A
5

It looks to me like you're looking for the ~@ macro expansion/unquote.

(defmacro defmethods [n & defs] 
   `(do ~@(map (fn [[a1 a2 a3]] 
                   `(def ~n ~a1 ~a2 ~a3)) 
               (partition 3 defs))))
Alible answered 5/9, 2011 at 22:25 Comment(3)
Thanks, I have written my defmethods now!Ecumenism
I think this pattern is easier to write as either (cons 'do (for [[x y z] (partition 3 args)] ...) or `(do ~@(for...))`. Map breaks up the flow of things, and using a backquote and ~@ just to get a cons makes the code look confusing.Coulee
@amalloy. Thanks for the tip. (do ~@(for...)) looks better.Ecumenism

© 2022 - 2024 — McMap. All rights reserved.