Clojure:在循环另一个集合的同时循环一个集合?

Clojure:在循环另一个集合的同时循环一个集合?,clojure,core.async,Clojure,Core.async,我有两个收藏x和y,它们的项目数量都不同。我想在x中循环并做一些有副作用的事情,同时在y中循环。我不想在循环x时重复y。doseq和for重复y: (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”]) 背景,我有一个文件的行和co

我有两个收藏
x
y
,它们的项目数量都不同。我想在
x
中循环并做一些有副作用的事情,同时在
y
中循环。我不想在循环
x
时重复
y
doseq
for
重复
y

(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
channels(比如5个),我想把每一行放到我的收藏中的下一个频道,比如:

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

如果将多个序列传递给
map
,它将在锁定步骤中逐步遍历每个序列,并使用每个序列中当前位置的值调用映射函数。当其中一个序列用完时停止

user> (map vector (range 5) (cycle ["A" "B"]))
([0 "A"] [1 "B"] [2 "A"] [3 "B"] [4 "A"])
在这种情况下,来自
(循环[“A”“B”])
的序列将永远产生As和Bs,尽管当来自
(范围5)
的序列结束时,map将停止使用它们。然后,每个步骤使用这两个参数调用向量函数,并将结果添加到输出序列中

对于第二个示例,使用go循环是扇出输入序列的一种相当标准的方法:

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)
user>(需要“[clojure.core.async:参考[go-go-loop!!>!chan-close!]”)
无
用户>(defn扇出[通道文件行]
(循环[[通道和通道](循环通道)
[行和行]文件行]
(如果行
(做
(>!ch行)
(重复chans行)
(doseq[c通道]
(关闭!c(())))
#'用户/扇出
用户>(定义行[“第一”、“第二”、“第三”、“第四”、“第五”])
#'用户/行
用户>(def测试通道[(通道)(通道)(通道)])
#'用户/测试通道
用户>(扇出测试通道线)
#

用户>(地图)(映射,所以,我必须获得结果,然后对其进行doseq以将其放入通道中?是的。在我个人看来,我喜欢将数据生成保留在它自己的功能中,这样我就可以独立于移动它的机制进行测试。是的,最终我希望保持我所有的功能的纯净,并在其上有一个层来管理推送从通道中调用和提取,所以这是可行的。请记住,您不能将通道操作
等放入映射函数中,因为go块不能跨越函数边界。嗯,对。另外,如果您查看我的实际示例,这些行将来自调用
(line seq rdr)
,其中与这里一样,所有数据都在一个值中。回到绘图板:)