我正在尝试实现一个简单的状态转换器,它使用ClojureScript来计数项目数量
(defn stateful-counter []
(fn [xf]
(let [counter (atom 0)]
(fn
([] (xf))
([result]
(xf (xf result @counter)))
([result _]
(swap! counter inc)
result)))))
当在序列上运行时,我得到以下输出
(into [] (stateful-counter) (range 5))
[5]
这正是我所预期的。
当在core.async通道上运行时,我得到一个无限的5序列
(go (println
(<! (let [c (async/chan 1 (stateful-counter))]
(async/onto-chan! c (range 5))
(async/into []
(async/take 10 c))))))
[5 5 5 5 5 5 5 5 5 5]
如果不使用(async/take 10 _),似乎会出现无限循环。预期的结果应该是[5]。
我还尝试使用来自xforms库的net.cgrand.xforms/count,并得到相同的不预期的结果
(go (println
(<! (let [c (async/chan 1 xforms/count)]
(async/onto-chan! c (range 5))
(async/into []
(async/take 10 c))))))
我曾假设我在状态计数器实现中犯了错误,导致循环。但我对xforms/count产生相同(不预期的)结果感到困惑。
这是一个ClojureScript片段,但我也能够用Clojure产生相同的不预期的结果。
有人能帮助我理解为什么应用状态转换器到core.async通道会导致无限序列吗?
编辑:在Clojure中也看到了相同的不预期的行为。