我想在列表中应用一系列测试,并确保所有测试都通过。 在Clojure中是否有类似“andmap”的函数?
答案 0 :(得分:9)
答案 1 :(得分:2)
Clojure 1.3将添加every-pred(以及“或”版本的相关some-fn)。
clojure.core /每-预解码值 ([p] [p1 p2] [p1 p2 p3] [p1 p2 p3& ps])
获取一组谓词并返回一个函数f,如果全部返回则返回true 组合谓词会针对其所有参数返回逻辑真值,否则返回 假。注意f是短路的,因为它将在第一个上停止执行 触发对原始谓词的逻辑错误结果的参数。
一个天真的实现可能是:
(defn every-pred [& preds](fn [& args](每个?#(每个?%args)preds)))
但实际实施会有更好的表现。
答案 2 :(得分:1)
every?
将询问“这个函数是否对seq的每个成员都返回true”,这与我认为你要求的接近。对every?
的改进将采用一系列函数并询问“这个seq的每个成员都是真的这些谓词”。
这是第一次尝试:
(defn andmap? [data tests]
(every? true? (for [d data, f tests]
(f d))))
user> (andmap? '(2 4 8) [even? pos?])
true
user> (andmap? '(2 4 8) [even? odd?])
false
答案 3 :(得分:1)
我写了andmap
作为一个宏,它以谓词作为参数,并构建了一个“在谓词周围包裹and
的函数”,即
(andmap integer? odd?)
==>
(fn [x] (and (integer? x)
(odd? x)))
(它没有扩展到完全这个,但它会扩展到与此相当的东西)
这样做的好处是它可以简化谓词,因此可以编写
(every? (andmap integer? odd?) [1 3 "a string"])
没有像Arthurs answer那样获得运行时异常。
以下是andmap
的定义:
(defmacro andmap ([] `(fn [& x#] true)) ([p & ps] `(fn [& x#] (and (apply ~p x#) (apply (andmap ~@ps) x#)))))
也可以将andmap
定义为一个函数,该函数由于惰性而使其谓词短路:
(defn andmap [& ps] (fn [& x] (every? true? (map (fn [p] (apply p x)) ps))))
tomap的谓词可以采用任意数量的参数,因此可以编写
(map (andmap #(and (integer? %1)
(integer? %2))
#(and (odd? %1)
(even? %2))
<)
[1 3 9]
[2 6 "string"])
评估为(true true false)
。