clojure“and”和“or”的非宏版本

时间:2011-04-03 19:38:59

标签: clojure

Clojure中是否存在andor的非宏版本?

更新:在这种情况下,我不关心短路。

5 个答案:

答案 0 :(得分:8)

or

函数some“返回coll中任何x的(pred x)的第一个逻辑真值,否则为nil。”

因此,您可以将(some identity coll)用于or。请注意,当最后一个值为or时,其行为将与false不同:它会返回nil or将返回false

and

如果您不需要知道coll向量中最后一个表单的值,则可以(every? identity coll)使用and。这将与and宏的行为不同,因为如果它的所有参数都是真实的,它将返回true。如果您需要最后一个表格的结果,请参阅larsmans的答案。

答案 1 :(得分:5)

land代表“逻辑和”,然后定义它们是微不足道的:

(defn land
  ([] true)
  ([x & xs] (and x (apply land xs))))

或者,稍微接近标准and行为:

(defn land
  ([] true)
  ([x] x)
  ([x & xs] (and x (apply land xs))))

同样适用于or

答案 2 :(得分:3)

最近在clojure-dev上实际上是came up as a topic。 Rich Hickey最终得出结论,他们应该被添加到1.3的核心,作为每个pred和any-pred(记录为CLJ-729)。我认为进一步的讨论使他们现在被称为every-pred(和变体)和some-fn(变体)。最终版本最近刚刚committed掌握。

答案 3 :(得分:1)

如果你的意思是功能:不,他们不能。原因是函数形式总是在将函数应用于它们的值之前评估它们的所有参数。你不想在这里。

答案 4 :(得分:1)

大多数情况下你想要这样做有更惯用的方法,但只是一个练习,可以通过thunking推迟评估。将您的表达式打包并将它们提供给逻辑运算符,以便在需要时使用标准和/或来评估thunk:

(defn &&* [& fns]
  (cond (= 1 (count fns)) ((first fns))
        :otherwise
        (and ((first fns)) (apply &&* (next fns)))))

(defn ||* [& fns]
  (cond (= 1 (count fns)) ((first fns))
        :otherwise
        (or ((first fns)) (apply ||* (next fns)))))

Example use:

(map 
  (partial apply &&*) 
    (map (partial map constantly) ;; thunk all of these values 
      [["yes" "no"] 
       [false true]
       [true "something"] 
       [true "something" "false"]]))

("no" false "something" "false")

另一个例子:

(defmacro thunks
  "convert expressions into thunks to prevent advance evaluation"
  [& exprs]
  (let [fns# (map (fn [e] `(fn [] ~e)) exprs)]
    (cons 'vector fns#)))

(apply ||* (thunks (+ 1 2) false (* 1 5)))
3
(apply &&* (thunks (+ 1 2) false (* 1 5)))
false
(apply &&* (thunks (+ 1 2) (* 1 5)))
5