在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/partition 3 c)]
    (when-let [v (<! p)]
      (prn v)
      (recur p))))

;;[0 1 2]
;;[3 4 5]
;;[6 7 8]


我意识到拥有这可能意味着能够多次从一个通道读取相同的值。我也知道我可以创建自己的函数,该函数可以根据需要从通道读取尽可能多的值,并构建自己的分区。

但是我想知道是否有任何办法可以使用core.async提供的核心API来实现这一目标。

PS。 sliding-buffer不能解决问题,因为我无法一次浏览整个缓冲区。

最佳答案

一种方法是创建一个从通道读取,缓冲值并放入新通道的函数。我不确定这是多么惯用。

例如,每当从输入通道中读取所需的put!项目时,下面的函数就会将矢量n进入输出通道,并在每次输出后跳过step项目。



(defn stepped-partition [in n step]
  (let [out (chan)]
    (go-loop [buffer []]
      (when-let [v (<! in)]
        (let [new-buffer (conj buffer v)]
          (if (= (count new-buffer) n)
            (do
              (put! out new-buffer)
              (recur (subvec new-buffer step)))
            (recur new-buffer)))))
   out))

(def original (chan))
(def partitioned (stepped-partition a 3 2))

(go-loop []
           (when-let [v (<! partitioned)]
             (println v)
             (recur)))

(async/onto-chan original [1 2 3 4 5 6 7 8 9])

;=> [1 2 3]
;=> [3 4 5]
;=> [5 6 7]
;=> [7 8 9]

09-16 00:05