我试图做下面的事情,
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
。
这样做的惯用方法是什么?
答案 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)))