“The first rule of macro club is: Don’t write macros”
I wrote this originally as an answer to a StackOverflow question. But the question got closed by some trigger-happy mods before I clicked post. How unfriendly!
Anyway, in case it is useful to people wondering when they should and shouldn’t use macros, I thought I would post it here instead….
Functions vs. Macros
I often get questions about when you should use functions vs. macros in Clojure / other Lisps. The rule is simple “don’t use macros unless you have to”. This post is about those cases where you have to use macros in Clojure, i.e. when functions cannot do the job.
The fundamental limitation with functions is that the rule for function application is fixed: at runtime, function parameters get eagerly evaluated in turn, and then the function itself is called with these parameters.
If you are happy with this approach then functions are fine, but there are cases where it won’t work. You need a macro if you want to get around one of the limitations of function application, for example:
- You don’t want to eagerly evaluate all arguments (e.g. in a **control structure**)
- You want some of the code to **run at compile time**, not at runtime
- You want a **custom syntax** which can’t be evaluated with the normal function evaluation rule – so you need to transform your custom syntax into something that can be executed first
Here are quick illustrations of these cases with Clojure.
Creating control structures: you can’t do this with a function, because you need to do the test before deciding whether or not to evaluate the body. Since functions always evaluate all their arguments, you can’t do this with a function:
(defmacro when-negative [test & body] `(if (< ~test 0) (do ~@body))) (when-negative -1 (println "Haz a negative number!")) => "Haz a negative number!"
Performing compile-time computation: if you compute a value in a macro, it will get turned into a constant at runtime. This can be helpful for various optimisations, for example the following macro will compute a constant at compile time:
(defmacro constant [body] (eval body)) (defn millis-since-compilation  (- (System/currentTimeMillis) (constant (System/currentTimeMillis)))) (millis-since-compilation) => 9196
Providing custom syntax: For example new binding forms that bind a value to a symbol in a loop. (compare to how long it took for Java to get a new `for (x : collection)` syntax, in Lisp/Clojure it’s a five-liner…..)
(defmacro for-loop [[sym init check change] & code] `(loop [~sym ~init value# nil] (if ~check (recur ~change (do ~@code)) value#))) (for-loop [i 0 (< i 10) (inc i)] (print i)) => 0123456789
Note that all of the above examples are quite special cases. Normal code shouldn’t need macros. You should normally start off with a function, and only reach for a macro when all else fails. Macros are more complex to write, harder to maintain and can’t be used flexibly in ways that functions can (e.g. passing to higher order functions).