我想运行这样的代码
(->> input
(partition-all 5)
(map a-side-effect)
dorun)异步分割输入输出(a-副作用)。
然后我编写了下面的实验代码。
;; using boot-clj
(set-env! :dependencies '[[org.clojure/core.async "0.2.374"]])
(require '[clojure.core.async :as async :refer [<! <!! >! >!!]])
(let [input (range 18)
c (async/chan 1 (comp (partition-all 5)
(map prn)))]
(async/onto-chan c input false)
(async/close! c))对此代码的解释:
async/onto-chan用于将元素(输入的片段)放入通道c中,并将多次调用,因此第三个参数是false。prn是a-side-effect的替代品。我希望上面的代码打印出来
[0 1 2 3 4]
[5 6 7 8 9]
[10 11 12 13 14]
[15 16 17]然而,在REPL中,它没有打印字符。
然后我增加了等待的时间,就像这样
(let [c (async/chan 1 (comp (partition-all 5)
(map prn)))]
(async/onto-chan c (range 18) false)
(Thread/sleep 1000) ;wait
(async/close! c))这段代码给出了上面我的预期输出。
然后我检查core.async/onto-chan。
我想发生了什么:
c频道是在我的代码中编辑的。core.async/onto-chan的每一项论证(core.async/>!)由于通道c被关闭,在onto-chan的go-loop中都是徒劳的。有明确的方法将项目放在close!之前吗?编写不使用onto-chan的同步版本的go-loop
还是我的想法错了?
发布于 2016-05-07 08:28:56
您使用Thread.sleep的第二个示例只是错误地“工作”。
它起作用的原因是,从c的换能器中得到的每个转换结果值都是nil,而且由于通道中不允许nil,因此抛出了异常,而c没有值:这就是允许生产者onto-chan继续放入通道而不是等待的原因。如果将第二个示例粘贴到REPL中,您将看到四个堆栈跟踪--每个分区一个。
当然,nil是由于prn上的映射而产生的,这是一个对所有输入返回nil的副作用函数。
如果我正确理解你的设计,你的目标是这样做:
(defn go-run! [ch proc]
(async/go-loop []
(when-let [value (<! ch)]
(proc value)
(recur))))
(let [input (range 18)
c (async/chan 1 (partition-all 5))]
(async/onto-chan c input)
(<!! (go-run! c prn)))go-loop消费者。map和副作用不能很好地结合在一起,所以我已经将副作用prn提取到了消费者中。onto-chan不能被称为“多次”(至少在显示的代码中是这样),因此它不需要false参数。发布于 2016-05-06 15:04:12
采纳了巨魔的想法:
(let [c (async/chan 1 (comp (partition-all 5)
(map prn)))
put-ch (async/onto-chan c (range 18) false)]
(async/alts!! [put-ch])
(async/close! c))https://stackoverflow.com/questions/37073900
复制相似问题