通过表达式进行条件线程处理

时间:2014-11-10 05:57:42

标签: clojure

我试图做下面的事情,

val = initValue;
if (test1(val)) { val = fn1(val); }
if (test2(val)) { val = fn2(val); }
return val;

我在clojure核心中找到的唯一方法是使用cond->。我希望我能够做到这一点

(cond-> initValue
   test1 fn1
   test2 fn2)

然而,cond->中的条件不是函数。它似乎不允许我将fn1的结果传递给test2

这样做的惯用方法是什么?

2 个答案:

答案 0 :(得分:1)

好。那么你在函数结果和谓词之间存在数据依赖关系,所以我只使用clojure.core创建的“最好的”是撰写as->cond->

(as-> initValue data
      (cond-> data (test1 data) (f1 data))
      (cond-> data (test2 data) (f2 data)))

另一种方法是我自己的update-when帮助......

(defn ->when-update
  "Function of a value, a predicate, an updater and optional
  varargs. If the predicate is true of the value, returns (apply f x
  args), otherwise returns x.

  Example:
    (-> 1 (->when-update #(<= 0 %) inc))"
  [x pred f & args]
  (if (pred x)
    (apply f x args)
    x))

让我们写

(-> initValue
    (->when-update test1 f1)
    (->when-update test2 f2))

答案 1 :(得分:0)

这会吗?

(defmacro cond-chain [init & stuff]
  (let [pairs (partition 2 stuff)
        step-form (fn [[test func]]
                    `((fn [x#] (if (~test x#) (~func x#) x#))))]
    (list* '->> init (map step-form pairs))))

例如,

(cond-chain 7, even? inc, odd? #(* 2 %))
;14

(cond-chain 7, odd? inc, odd? #(* 2 %))
;8

(cond-chain 7, zero? inc, even? #(* 2 %))
;7

正如您所看到的,它构造了一个有条件地应用一系列函数的表单。


或者,不使用宏:

(defn cond-chain [init & stuff]
  (let [pairs (partition 2 stuff)]
    (reduce (fn [acc [test func]] (if (test acc) (func acc) acc)) init pairs)))