给定->>
像这样的管道:
(defn my-fn []
(->> (get-data)
(do-foo)
(do-bar)
(do-baz)))
Run Code Online (Sandbox Code Playgroud)
我希望各个阶段都有条件.
想到的第一种写作方式就是这样:
(defn my-fn [{:keys [foo bar baz]}]
(->> (get-data)
(if foo (do-foo) identity)
(if bar (do-bar) identity)
(if baz (do-baz) identity))
Run Code Online (Sandbox Code Playgroud)
但是,当->>
宏试图插入if
表单时,这不仅在性能方面看起来很不幸(有noop identity
调用),而且实际上无法编译.
什么是合适的,合理干燥的写作方式是什么?
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
Run Code Online (Sandbox Code Playgroud)
当使用需要在参数列表中的不同点处线程化表达式的混合函数(即,从 - >切换到 - >>语法)时,这提供了很大的灵活性.为了代码可读性,应该避免使用无关的命名变量,但这通常是表达过程最清晰,最简单的方法.
还有cond->
,它要求一组对:测试和表达式,如果该测试评估为真.这非常相似,cond
但并未停留在第一次真正的测试中.
这也有效:
(defn my-fn [{:keys [foo bar baz]}]
(->> (get-data)
(#(if foo (do-foo %) %))
(#(if bar (do-bar %) %))
(#(if baz (do-baz %) %)) ))
Run Code Online (Sandbox Code Playgroud)
您可以修复编译部分(虽然不是苦行部分,通过让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)))
Run Code Online (Sandbox Code Playgroud)
将扩展为一系列如下调用:
; choose function and call it
( (if foo do-foo identity) args )
( (if bar do-bar identity) args )
( (if baz do-baz identity) args )
Run Code Online (Sandbox Code Playgroud)
如果你经常需要这种东西,那么更常见的方法是:
(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)))
归档时间: |
|
查看次数: |
2239 次 |
最近记录: |