我正在浏览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)))
答案 0 :(得分:9)
因为参数x
是一个表单,可能是任何表达式,可以在(if ~x (and ~@next) ~x))
中计算两次。 let
会对其进行一次评估,然后使用值 x#
。
因此,实际的代码可以避免两次评估参数的影响 - 特别是副作用。
@amalloy指出,x
中的(if ~x (and ~@next) ~x))
形式的第二个实例仅在第一个实例评估为false(y)时才会被计算。