2012-08-01 43 views
7

給出一個->>管道,像這樣:條件元素>>管道

(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調用),但實際上無法編譯。

什麼是適當的,合理的DRY寫作方式?

+0

'get-data'是否會像' - >>'通常使用的那樣返回一個序列? 'do-'函數是否會調用副作用,或者獲取/返回什麼? – 2012-08-01 22:31:50

+0

看起來不太可能,如果在線程調用中會以任何可感知的方式損害性能 – 2012-08-01 22:49:00

+0

@AlexTaggart是的,'get-data'返回一個序列 - 可能是一個很長的序列,使得它成爲一個內部循環。 'do- *'功能是純粹的,沒有副作用;也許我在這個例子中糟糕的命名了代碼。 – 2012-08-01 22:55:47

回答

6

現代的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非常相似,但並不止於第一次真正的測試。

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  ) 
+0

謝謝!我一直在引用我的fns,即'((如果foo'do-foo'身份)參數) - 你的例子幫助我調試了我的問題! – 2018-01-14 07:18:24

6

這工作太:

(defn my-fn [{:keys [foo bar baz]}] 
    (->> (get-data) 
     (#(if foo (do-foo %) %)) 
     (#(if bar (do-bar %) %)) 
     (#(if baz (do-baz %) %)))) 
4

一個更普遍的方式,如果你需要這樣的事情經常去:

 
(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))) 
7

你可能有興趣在這些宏https://github.com/pallet/thread-expr

+0

+1表示不要重新發明車輪。 :)我已經使用了你的線程表達庫,它很簡單,小巧,優雅,並且工作正常。 – Gert 2012-08-02 12:35:07

+0

你是在提出'(when-> foo do-foo)'還是另一種用法? – 2012-08-02 13:26:50