Clojure core.async中的重叠分区
在Clojure中,我可以通过将Clojure core.async中的重叠分区,clojure,core.async,Clojure,Core.async,在Clojure中,我可以通过将step参数调优为partition来获得集合的重叠分区: (partition 3 1 (range 20)) ;; ((0 1 2) (1 2 3) (2 3 4) (3 4 5) ...) core.async确实有一个分区函数,但由于它不接受step参数,因此无法获得重叠分区: (let [c (chan)] (go (doseq [n (range 20)] (>! c n))) (go-loop [p (async/
step
参数调优为partition
来获得集合的重叠分区:
(partition 3 1 (range 20))
;; ((0 1 2) (1 2 3) (2 3 4) (3 4 5) ...)
core.async确实有一个分区函数,但由于它不接受step参数,因此无法获得重叠分区:
(let [c (chan)]
(go (doseq [n (range 20)]
(>! c n)))
(go-loop [p (async/partition 3 c)]
(when-let [v (<! p)]
(prn v)
(recur p))))
;;[0 1 2]
;;[3 4 5]
;;[6 7 8]
(让[c(chan)]
(go(doseq[n(范围20)]
(>!cn)))
(go循环[p(异步/分区3C)]
(何时出租(
我意识到这可能意味着能够从一个通道多次读取相同的值。我还意识到,我可以创建自己的函数,从一个通道读取任意多的值,并构建自己的分区
然而,我想知道是否有任何方法可以通过core.async提供的核心API实现这一点
PS.滑动缓冲区
不起作用,因为我不能一次窥视整个缓冲区。嗯,我想这个愿望
“能够多次从通道读取相同的值”
与core.async的原则相反
每次从通道读取值时,都是从通道中取出该值
因此,通道行为的好处在于,它保证每个值只读取一次,如果没有值,则不读取(阻塞/停止线程),如果通道关闭,则为零
然后,开始解决问题的下一个问题应该是:为什么(在core.async上)至少有3个不同的函数在通道上输入/输出值。
因此,将通信通道视为一个集合点,在读写器可用之前,存在(core.async)3种不同的应用程序/线程行为:
- 阻塞线程<代码>>!!正在运行的线程将被阻塞,直到读卡器和写卡器都可用
- 停止线程(使用go宏块)
!go块将创建一个伪线程,该线程将被停止,直到读写器都可用。此行为不会阻止正在运行的线程
- 异步行为
take!put!
您只能按照写入和读取的顺序得到保证
实现这一点的一种方法是创建一个函数,从通道读取数据、缓冲值并将其放入新通道。不过,我不确定这有多习惯
例如,每当从输入通道读取所需的n
项时,下面的函数将put!
向量放入输出通道,在每次输出后跳过step
项
(defn步进分区[在n步中]
(放[出(陈)]
(go循环[缓冲区[]]
(当让[v([1 2 3]
;=> [3 4 5]
;=> [5 6 7]
;=> [7 8 9]
Hmm,可能最好使用异步/分区源的数组复制方法,而不是使用可能会消耗内存的向量?谢谢。这就是我所做的。它不会使core.async变得更容易。我会将你的方法标记为已接受,因为它与我拥有的非常接近。Re:eating memory,clojure.core/subvec
确实会生成保留原始输入向量的向量,因此内部缓冲区最终将保留放置在通道上的所有值(而放置在out
通道上的向量将保留到生成时看到的值)。一个简单的解决方法是在每次迭代的子向量
调用的结果上调用vec
;结果将是一个在线性时间内构造的新向量。或者,您也可以使用实(非视图)O(对数n)切片。不过,一致认为可能最好只使用数组。