Search code examples
clojure

About the source of the and macro


I was browsing the source of clojure.core:

(defmacro and
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

Why not just

(defmacro and
  ([] true)
  ([x] x)
  ([x & next]
   `(if ~x (and ~@next) ~x)))

Solution

  • Because the argument x is a form, which might be any expression, that can be evaluated twice in (if ~x (and ~@next) ~x)). The letevaluates it once and uses the value x# thereafter.

    So the actual code avoids the effects - the side effects in particular - of evaluating the arguments twice.


    @amalloy points out that the second instance of form x in (if ~x (and ~@next) ~x)) is evaluated only if the first instance evaluates false(y).