是否有线程化的方式在Clojure中执行“或”(或任何测试)条件?

时间:2019-05-15 20:35:12

标签: clojure

类似的东西:

(or->
    "foobar"
    (clojure.string/starts-with? "foo")
    (clojure.string/starts-with? "bar"))

=> true

如果没有,用多个or / and进行测试的惯用方式是什么?

3 个答案:

答案 0 :(得分:9)

我在这里使用some。本质上,这是一个顺序友好的or检查,当所有条件基本相同时,可以帮助减少重复:

(some #(clojure.string/starts-with? "foobar" %)
      ["foo" "bar"])

它使用早期回报。


and等效的someevery?

(every? odd? [3 5 9])
=> true

答案 1 :(得分:3)

我们需要在所有连续子句中对其进行插入之前将第一个参数插入。因此,解决方案必须是宏。如果我们准备不进行语法检查,则可以非常简洁地定义它:

(defmacro or-> [arg & pred-exprs]
  (let [insert-expr (fn [[x & xs]] (list* x arg xs))
        inserted-exprs (map insert-expr pred-exprs)]
    (cons 'or inserted-exprs)))

有效:

problem=> (or-> "foobar" 
                (clojure.string/starts-with? "foo")
                (clojure.string/starts-with? "bar"))
true

problem=> (or-> "foobar"
                (clojure.string/starts-with? "for")
                (clojure.string/starts-with? "bar"))
false

但是它为尝试的每个子句评估arg格式。要只评估一次arg形式,我们为let插入gensym形式:

(defmacro or-> [arg & pred-exprs]
  (let [arg-sym (gensym)
        insert-arg (fn [[x & xs]] (list* x arg-sym xs))
        inserted-exprs (map insert-arg pred-exprs)]
    `(let [~arg-sym ~arg] (or ~@inserted-exprs))))

我想用auto-gensym做到这一点,但是我想出了办法。但是,这样做并不是正常的Clojure意义上的线程化,而是始终执行所有线程化子句。

答案 2 :(得分:2)

通常,您确实需要使用<group> <p id="111">5tw5t5et</p> <p id="111">4qvtq3</p> </group> <p id="222">qv34tqv3</p> <j>qv43tvq</j> <group> <p id="333">qv43tvq</p> <p id="333">q34tvq43tvq</p> <p id="333">q3434t3tvq43tvq</p> </group> 和一个符号:

or