在clojure中是否有类似“andmap”的功能?

时间:2009-07-30 22:49:25

标签: clojure

我想在列表中应用一系列测试,并确保所有测试都通过。 在Clojure中是否有类似“andmap”的函数?

4 个答案:

答案 0 :(得分:9)

您可以使用every?

user=> (every? string? '("hi" 1))
false

以下是every?的文档。

答案 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)