Clojure 通过表达式的条件线程
我试着做下面的事情Clojure 通过表达式的条件线程,clojure,Clojure,我试着做下面的事情 val = initValue; if (test1(val)) { val = fn1(val); } if (test2(val)) { val = fn2(val); } return val; 我在clojure core中找到的唯一方法是使用cond->。我希望我能做到这一点 (cond-> initValue test1 fn1 test2 fn2) 但是,cond->中的条件不是函数。它似乎不允许我将fn1的结果传递给test2 这样做的惯
val = initValue;
if (test1(val)) { val = fn1(val); }
if (test2(val)) { val = fn2(val); }
return val;
我在clojure core中找到的唯一方法是使用cond->
。我希望我能做到这一点
(cond-> initValue
test1 fn1
test2 fn2)
但是,cond->
中的条件不是函数。它似乎不允许我将fn1
的结果传递给test2
这样做的惯用方法是什么?好的。函数结果和谓词之间存在数据依赖关系,因此我仅使用clojure.core提出的“最好的”方法是将
as->
和cond->
(as-> initValue data
(cond-> data (test1 data) (f1 data))
(cond-> data (test2 data) (f2 data)))
另一种方法是我自己的助手
(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))
这样行吗
(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)))
(defn cond-chain [init & stuff]
(let [pairs (partition 2 stuff)]
(reduce (fn [acc [test func]] (if (test acc) (func acc) acc)) init pairs)))