给出->>
这样的管道:
(defn my-fn []
(->> (get-data)
(do-foo)
(do-bar)
(do-baz)))
我希望各个阶段都有条件。
第一种写出来的想法就是这样:
(defn my-fn [{:keys [foo bar baz]}]
(->> (get-data)
(if foo (do-foo) identity)
(if bar (do-bar) identity)
(if baz (do-baz) identity))
但是,当->>
宏尝试插入if
表单时,这不仅在性能方面看起来很不幸(具有noop identity
调用),但实际上未能编译。
什么是合适的,合理干燥的写作方式?
答案 0 :(得分:8)
答案 1 :(得分:8)
Modern Clojure(即1.5版)支持条件线程的各种选项。
as->
也许是最多才多艺的,通过给你一个名称来引用"事物"穿过表格。例如:
(as-> 0 n
(inc n)
(if false
(inc n)
n))
=> 1
(as-> 0 n
(inc n)
(if true
(inc n)
n))
=> 2
当使用需要在参数列表中的不同点处线程化表达式的混合函数(即,从 - >切换到 - >>语法)时,这提供了很大的灵活性。为了代码可读性,应该避免使用无关的命名变量,但这通常是表达过程最清晰,最简单的方法。
还有cond->
,它要求一组对:测试和表达式,如果该测试评估为真。这与cond
非常相似,但在第一次真实测试时并没有停止。
答案 2 :(得分:7)
这也有效:
(defn my-fn [{:keys [foo bar baz]}]
(->> (get-data)
(#(if foo (do-foo %) %))
(#(if bar (do-bar %) %))
(#(if baz (do-baz %) %)) ))
答案 3 :(得分:5)
如果你经常需要这种东西,那就是更常见的方法:
(defn comp-opt [& flag-fns] (->> flag-fns (partition 2) (filter first) (map second) (apply comp))) (defn my-fn [{:keys [foo bar baz]}] (map (comp-opt foo do-foo bar do-bar baz do-baz) (get-data)))
答案 4 :(得分:4)
你可以修改编译部分(虽然不是禁欲部分,但是通过使用另一组( )
来确定 if语句决定运行哪个函数:
(defn my-fn [{:keys [foo bar baz]}]
(->> (get-data)
((if foo do-foo identity))
((if bar do-bar identity))
((if baz do-baz identity)))
会扩展为一系列这样的调用:
; choose function and call it
( (if foo do-foo identity) args )
( (if bar do-bar identity) args )
( (if baz do-baz identity) args )