clojure - 如何构建一个阻塞的分块惰性序列?

标签 clojure lazy-sequences

我想使用分块 cons 或其他方式来创建一个阻塞的lazy-seq。给定来源:

(defn -source- [] (repeatedly (fn [] (future (Thread/sleep 100) [1 2]))))

(take 2 (-source-))
;; => (<future> <future>)

我想要一个名为 injest 的函数,其中:

(take 3 (injest (-source-)))
=> [;; sleep 100
    1 2 
    ;; sleep 100
    1]

(take 6 (injest (-source-)))
=> [;; sleep 100
    1 2 
    ;; sleep 100
    1 2 
    ;; sleep 100
    1 2]

;; ... etc ...

我该如何编写这个函数?

最佳答案

当您使用该源时,它会自然地阻塞,因此您不必做任何非常花哨的事情。简单地 (mapcat deref) 就足够了:

(doseq [x (take 16 (mapcat deref (-source- )))]
  (println {:value x :time (System/currentTimeMillis)}))
{:value 1, :time 1597725323091}
{:value 2, :time 1597725323092}
{:value 1, :time 1597725323092}
{:value 2, :time 1597725323093}
{:value 1, :time 1597725323093}
{:value 2, :time 1597725323093}
{:value 1, :time 1597725323194}
{:value 2, :time 1597725323195}
{:value 1, :time 1597725323299}
{:value 2, :time 1597725323300}
{:value 1, :time 1597725323406}
{:value 2, :time 1597725323406}
{:value 1, :time 1597725323510}
{:value 2, :time 1597725323511}

请注意前几项是如何同时出现的,然后每对都按照您预期的时间错开?这是由于众所周知的(?)事实,apply(因此使用 apply concat 实现的 mapcat)更加渴望出于性能原因,超出必要的范围。如果即使在前几个项目上获得正确的延迟对您来说也很重要,您可以简单地实现您自己的 apply concat 版本,该版本不会针对短输入列表进行优化。

(defn ingest [xs]
  (when-let [coll (seq (map (comp seq deref) xs))]
    ((fn step [curr remaining]
       (lazy-seq
         (cond curr (cons (first curr) (step (next curr) remaining))
               remaining (step (first remaining) (next remaining)))))
      (first coll) (next coll))))

A. Webb 在评论中建议了一个等效但更简单的实现:

(defn ingest [coll]
  (for [batch coll,
        item @batch]
    item))

关于clojure - 如何构建一个阻塞的分块惰性序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63461570/

相关文章:

macros - 在 Clojure 宏中引用基于 ~ 和 ~@ 的选择

"partition"函数实现中的递归

ruby - 如何制作一个通过其他两个枚举器进行延迟迭代的 ruby​​ 枚举器?

scala - Scala 可变集合的 View 有什么惰性?

javascript - Nashorn - 同步 Java 与异步 Javascript 阻抗不匹配

clojure - (= [ :a :b] (list :a :b)) returns true in clojure?

scala - clojure在scala中迭代等效?

clojure - 无法调用非公共(public)类的公共(public)方法: public (Google gcloud library)

c++ - 标准 C++11 是否保证传递给函数的临时对象会在函数结束后被销毁?

python - 有没有办法在 Python 中构造惰性序列?