- >中的条件元素/ - >>管道

时间:2012-08-01 21:36:12

标签: clojure

给出->>这样的管道:

(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调用),但实际上未能编译。

什么是合适的,合理干燥的写作方式?

5 个答案:

答案 0 :(得分:8)

您可能对这些宏https://github.com/pallet/thread-expr

感兴趣

答案 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       )