[英]How to prevent close!-ing before put-ing in onto-chan
I'd like to run a code like 我想运行类似的代码
(->> input
(partition-all 5)
(map a-side-effect)
dorun)
asynchronously dividing input and output(a-side-effect). 异步划分输入和输出(a副作用)。
Then I've written the code to experiment below. 然后,我编写了代码进行下面的实验。
;; 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))
explanation for this code: 此代码的说明:
async/onto-chan
is used to put a Seq of elements (a fragment of input) into the channel c
and will be called many times thus the 3rd argument is false
. async/onto-chan
用于将Seq元素(输入的一部分)放入通道c
,将被调用多次,因此第3个参数为false
。 prn
is a substitute for a-side-effect
. prn
是prn
a-side-effect
的替代品。 I expected the code above prints 我期望上面的代码可以打印
[0 1 2 3 4]
[5 6 7 8 9]
[10 11 12 13 14]
[15 16 17]
in REPL however it prints no characters. 在REPL中,但是不打印任何字符。
And then I add a time to wait, like this 然后我增加了等待时间,就像这样
(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))
This code gave my expected output above. 这段代码在上面给出了我的预期输出。
And then I inspect core.async/onto-chan
. 然后我检查
core.async/onto-chan
。
And I think what happend: 我认为发生了什么:
c
was core.async/close!
c
是core.async/close!
ed in my code. core.async/onto-chan
was put( core.async/>!
) in vain in the go-loop
in onto-chan
because the channel c
was closed. core.async/onto-chan
放入( core.async/>!
白白在go-loop
在onto-chan
因为信道c
被关闭。 Are there sure ways to put items before close!
有确定的方法可以在
close!
之前放置物品close!
ing? 恩? write a synchronous version of
onto-chan
not using go-loop
? 写一个不使用
go-loop
的onto-chan
的同步版本?
Or is my idea wrong? 还是我的想法错了?
Your second example with Thread.sleep
only 'works' by mistake. 您使用
Thread.sleep
第二个示例仅错误地“起作用”。
The reason it works is that every transformed result value that comes out of c
's transducer is nil
, and since nil
s are not allowed in channels, an exception is thrown, and no value is put into c
: this is what allows the producer onto-chan
to continue putting into the channel and not block waiting. 它起作用的原因是,从
c
的转换器产生的每个转换结果值均为nil
,并且由于不允许在通道中使用nil
,因此将引发异常,并且不会将任何值放入c
: onto-chan
继续放入频道,而不是等待。 If you paste your second example into the REPL you'll see four stack traces – one for each partition. 如果将第二个示例粘贴到REPL中,则会看到四个堆栈跟踪-每个分区一个。
The nil
s are of course due to mapping over prn
, which is a side-effecting function that returns nil
for all inputs. nil
当然是由于映射到prn
,这是一个副作用函数,对于所有输入都返回nil
。
If I understand your design correctly, your goal is to do something like this: 如果我正确理解您的设计,则您的目标是执行以下操作:
(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
consumer. go-loop
消费者。 map
and side-effects don't go together well, so I've extracted the side-effecting prn
into the consumer. map
和副作用不一起去好了,所以我已经提取的副作用的prn
进入消费。 onto-chan
cannot be called 'many times' (at least in the code shown) so it doesn't need the false
argument. onto-chan
称为“很多次”(至少在所示代码中如此),因此它不需要false
参数。 taking megakorre's idea: 接受megakorre的想法:
(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))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.