简体   繁体   English

在放入close前如何防止关闭!

[英]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: 此代码的说明:

  • Actually elements in input and its quantity is not defined before running and elements in input is able to be taken by some numbers from 0 to 10. 实际上,在运行之前未定义输入中的元素及其数量,输入中的元素可以使用0到10之间的某个数字。
  • 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 . prnprn 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: 我认为发生了什么:

  1. the channel c was core.async/close! 通道ccore.async/close! ed in my code. 在我的代码中
  2. each item of the argument of 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-looponto-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-looponto-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 ,因此将引发异常,并且不会将任何值放入conto-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)))
  • You really do need a producer and a consumer, else your program will block. 您确实确实需要生产者和消费者,否则您的程序将被阻塞。 I've introduced a go-loop consumer. 我介绍了一个go-loop消费者。
  • Very generally speaking, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM