Clojure"和"宏作为一种象征

时间:2015-02-20 13:26:17

标签: clojure

为什么以下语句会返回不同的结果?而且,如何编写第二个语句来接收假的结果?

(clojure.core/and false true)
=> false

((resolve 'clojure.core/and) false true)
=> true

1 个答案:

答案 0 :(得分:3)

freenode上#clojure的好心人帮我一个答案。 首先,应该尽量避免在运行时解析宏。 其次,宏功能被实现为除了任何(&)args之外还接收两个参数的函数。因此,编写上述第二个语句的正确方法是

((resolve 'clojure.core/and) nil nil false true) => 
**(clojure.core/let [and__3973__auto__ false] (if and__3973__auto__ (clojure.core/and true) and__3973__auto__))**

由于我们仍在使用宏,它只是将其扩展为代码,而不是返回实际值。 AND作为宏实现的原因是使短路成为可能。 你可以从REPL看到:

(defmacro and
  "Evaluates exprs one at a time, from left to right. If a form
  returns logical false (nil or false), and returns that value and
  doesn't evaluate any of the other expressions, otherwise it returns
  the value of the last expr. (and) returns true."
  {:added "1.0"}
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))

如果没有宏,AND函数将评估给定的所有谓词而不会发生短路。 在我的特殊情况下,这正是我所需要的;用于AND和OR非短路功能。 以下是两种功能,以防任何人需要它们:

(defn and* [& xs] (every? identity xs))
(defn or* [& xs] (not= (some true? xs) nil))