1

I have this recursive macro m1 which is called by macro m1-do. The purpose is to generate some function calls.

(defmacro m1 [fname x]
  (if (= (count x) 1)
    (let [a0 (first x)]
      `(~fname ~a0))
    (let [[a0 & arest] x]
      `((~fname ~a0) (m1 ~fname ~arest)))))

(defmacro m1-do [fname x]
  `(do (m1 ~fname ~x)))

This is what I want to achive as a result:

(m1-do f1 (45 98 122 143 215)) =>
(do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))

But instead I get an additional parenthesis level on each recursion. The first result already has too many of them:

user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98)))
(do ((f1 45) (f1 98)))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122)))
(do ((f1 45) ((f1 98) (f1 122))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143)))
(do ((f1 45) ((f1 98) ((f1 122) (f1 143)))))
user=> (clojure.walk/macroexpand-all '(m1-do f1 (45 98 122 143 215)))
(do ((f1 45) ((f1 98) ((f1 122) ((f1 143) (f1 215))))))

The problem seems that each call returns a list, which adds another pair of () and I also tried to develop some flattening function and use it within the macro with no success.

The numbers are only placeholders for the real content which is more complex.

2
  • I have seen this answer which uses cons: stackoverflow.com/a/5261744/1431660 I could not make it work with cons because I run into quoting / unquoting issues. Commented Nov 15, 2015 at 20:40
  • I edited the example and removed one level of parenthesis in code line 4, but this does not help much. Commented Nov 15, 2015 at 20:45

1 Answer 1

3

You could do it with a very simple non-recursive macro:

(defmacro m1-do [fname coll]
  `(do ~@(map (partial list fname) coll)))

Here is how you could do the same thing with cons:

(defmacro m1-do [fname coll]
  (cons 'do (map (partial list fname) coll)))

Both versions are exactly the same and produce desires output:

(macroexpand '(m1-do f1 (45 98 122 143 215)))
; => (do (f1 45) (f1 98) (f1 122) (f1 143) (f1 215))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.