关于和宏的来源

时间:2017-01-22 02:00:13

标签: clojure

我正在浏览clojure.core的来源:

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

为什么不

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

1 个答案:

答案 0 :(得分:9)

因为参数x是一个表单,可能是任何表达式,可以在(if ~x (and ~@next) ~x))中计算两次。 let会对其进行一次评估,然后使用 x#

因此,实际的代码可以避免两次评估参数的影响 - 特别是副作用。

@amalloy指出,x中的(if ~x (and ~@next) ~x))形式的第二个实例仅在第一个实例评估为false(y)时才会被计算。