clojure

How to pass list of args to variadic macro


I have a macro (I've simplified everything a lot):

(defmacro m1 [error & messages]
  `(if ~error
     (str "Error: " ~@messages)
     (str ~@messages)))

It works pretty well. But now I want to reuse it in a function with args [& messages]:

If I define this function the following way:

(defn error [& messages]
  (m1 true messages))

It works, but incorrectly of course. If I call (error "msg") it returns "Error: (\"msg\")"

But if I do something like:

(defn error [& messages]
  (apply m1 true messages))

It causes an error

; Syntax error compiling at .... ; Can't take value of a macro

So the question is how to pass messages list to variadic macro?


Solution

  • You cannot. Macros operate at macro expansion time, and there, messages is just a symbol.

    m1 doesn't need to be a macro at all - it can be a plain function. And whenever you can use a function instead of a macro, you should most definitely do so to avoid any similar issues.