Last Updated: February 25, 2016
·
1.146K
· hsestupin

Why "when" is a macro?

Yesterday I was suddenly struck by the question "Why clojure word "when" is implemented as a macro?". Why Rich couldn't write just something like this:

(defn when [test & body] 
  (if test (last body)))

instead of current implementation:

(defmacro when
  "Evaluates test. If logical true, evaluates body in an implicit do."
  {:added "1.0"}
  [test & body]
  (list 'if test (cons 'do body)))

Spending several minutes to think about and I had come to conclusion. The only reason is that arguments passed to macro are not evaluated. They are passed to macro just as lists. So here is the big difference:

(clojure.core/when false (println "123") (+ 3 5))
-> nil

; my dumb implementation
(user/when false (println "123") (+ 3 5))
-> 123
nil

So the difference is that all of the arguments are being evaluated only if the condition is true. It clears your code from side-effects and I guess its actually right behaviour.

Are there any other reasons to use macro at this case?