arn*_*nab 4 clojure core.async
我有两个集合x,并y均具有不同数量的项目.我想在循环中循环x并做一些有副作用的事情y.y循环时我不想重复x.双方doseq并for重复y:
(for [x (range 5)
y ["A" "B"]]
[x y])
Run Code Online (Sandbox Code Playgroud)
这产生了([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)))))
Run Code Online (Sandbox Code Playgroud)
如果您传递多个序列,map则在锁定步骤中逐步执行每个序列,使用每个序列中的当前位置调用映射函数.当其中一个序列用完时停止.
user> (map vector (range 5) (cycle ["A" "B"]))
([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])
Run Code Online (Sandbox Code Playgroud)
在这种情况下,序列来自(cycle ["A" "B"])将继续产生As和Bs,尽管当序列(range 5)结束时map将停止消耗它们.然后,每一步都使用这两个参数调用vector函数,并将结果添加到输出序列中.
对于使用循环的第二个示例,是一种扇出输入序列的相当标准的方法:
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 clojure.core.async.impl.channels.ManyToManyChannel@3b363fc5>
user> (map <!! test-chans)
("first" "second" "third")
user> (map <!! test-chans)
("fourth" "fifth" nil)
Run Code Online (Sandbox Code Playgroud)