谓词收集的短循环真实检验

时间:2016-12-27 11:49:25

标签: clojure

假设需要检查参数是否通过给定谓词集合的一个真值测试。

codewise:

<body>
    <input type="text" name="item" id="txt_search" list="item_list">
    <datalist id="item_list">
    <?php
        foreach($arr as $a)
        {
            echo "<option>".$a['product']."</option>";
            //$a['id']
        }
    ?>
    </datalist>
</body>

由于(fn [x] (or (pred1 x) (pred2 x) (pred3 x) (pred4 x))) 的实施,这是第一个真正价值之后的短路。按照预期。

如何使用谓词集合重写:

[pred1 pred2 pred3 pred4]

一种时髦的方式是:

or

事实证明,这个不会短路。可能是由于Clojure对懒惰序列的分块。

我们可以做得更好吗?

4 个答案:

答案 0 :(得分:4)

clojure具有some-fn功能:

user> ((some-fn true? false? nil?) true)
true
user> ((some-fn  false? nil?) true)
false

或您的情况:

user> (defn any-pred? [x preds]
        ((apply some-fn preds) x))

另一种经典的方法是递归地执行:

user> (defn any-pred? [x preds]
        (when-let [[pred & preds] (seq preds)]
          (or (pred x) (any-pred? x preds))))

user> (any-pred? true [false?])
nil
user> (any-pred? true [true?])
true
user> (any-pred? true [false? true?])
true
user> (any-pred? true [false? nil?])
nil
user> (any-pred? true [false? nil? true?])
true

答案 1 :(得分:0)

当我需要短路时,我会使用reduce减少。

(defn any-valid? [w & pred-fn-coll]
  (reduce (fn [v pf]
        (if (pf w)
          (reduced true)
          v)) false pred-fn-coll))

 (any-valid? 1 even? odd?)
 ;=> true
 (any-valid? 1 even? even?)
 ;=> false

答案 2 :(得分:0)

我认为这是map正在你的解决方案中进行分块。

尝试

(defn any-true? [preds]
  (fn [x]
    (loop [preds preds]
      (and (seq preds)
           (or ((first preds) x)
               (recur (rest preds)))))))

((any-true? [odd? even?]) 3)    ;true

((any-true? []) 3)              ;nil

((any-true? [even?]) 3)         ;nil

((any-true? [odd? #(/ % 0)]) 3) ;true

最后一个例子表明评估是懒惰的。

答案 3 :(得分:0)

可替换地,

(defn somep? [x [p & ps :as preds]]
  (if-not (empty? preds)
    (or (p x) (somep? x ps))))

(defn somep? [x [p & ps :as preds]]
  (if-not (empty? preds)
    (let [res (p x)]
      (if-not res
        (recur x ps)
        res))))