2015-03-13 76 views
3

我有兩個系列xy,都有不同數量的項目。我想通過x循環,並做一些副作用,而通過y騎自行車。我不想在通過x循環時重複y。既doseqfor重複yClojure:在循環另一個集合的同時循環一個集合?

(for [x (range 5) 
     y ["A" "B"]] 
    [x y]) 

這產生([0 "A"] [0 "B"] [1 "A"] [1 "B"] [2 "A"] [2 "B"] [3 "A"] [3 "B"] [4 "A"] [4 "B"])

我想要的是會產生的東西:([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])

背景,我有一個文件行和core.async渠道(比如5),我希望把每行到下一個通道在我的收藏,是這樣的:

(defn load-data 
    [file chans] 
    (with-open [rdr (io/reader file)] 
    (go 
     (doseq [l (line-seq rdr) 
       ch chans] 
     (>! ch l))))) 

回答

7

如果傳遞到多個序列map它在鎖步驟中逐步通過它們中的每一個來調用具有來自每個當前位置的值的映射函數。當其中一個序列用完時停止。

user> (map vector (range 5) (cycle ["A" "B"])) 
([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"]) 

在這種情況下,從(cycle ["A" "B"])序列將繼續生產As和燒烤永遠雖然地圖會停止食用它們(range 5)結束序列時。每一步然後用這兩個參數調用向量函數,並將結果添加到輸出序列中。

和第二例使用去環是散開的輸入序列的一個相當標準的方法:

user> (require '[clojure.core.async :refer [go go-loop <! <!! >!! >! chan close!]]) 
nil 
user> (defn fanout [channels file-lines] 
     (go-loop [[ch & chans] (cycle channels) 
        [line & lines] file-lines] 
      (if line 
      (do 
       (>! ch line) 
       (recur chans lines)) 
      (doseq [c channels] 
       (close! c))))) 
#'user/fanout 
user> (def lines ["first" "second" "third" "fourth" "fifth"]) 
#'user/lines 
user> (def test-chans [(chan) (chan) (chan)]) 
#'user/test-chans 
user> (fanout test-chans lines) 
#<ManyToManyChannel [email protected]> 
user> (map <!! test-chans) 
("first" "second" "third") 
user> (map <!! test-chans) 
("fourth" "fifth" nil) 
+0

因此,我將不得不採取的這個結果,然後doseq在它把它放入渠道? – arnab 2015-03-13 17:09:41

+0

是的。我個人認爲,我喜歡將數據生成保存在自己的函數中,這樣我就可以獨立於移動它的機制來進行測試。 – 2015-03-13 17:11:37

+0

是的,最終我想保持我所有的功能都是純粹的,並且有一層可以管理頻道推送和拉取的功能,所以這是有效的。 – arnab 2015-03-13 17:13:22