关于core.async:等待Clojure异步通道的惯用方式是什么?

What is the idiomatic way of waiting for a Clojure async channel?

这是代码的当前版本,非常简单。 它启动10个go例程,每个例程向该通道添加10条消息。 另一端是一个while true循环,该循环读取通道并每500 ms超时一次。

我正在考虑有更好的东西。 我认为while真正的循环可以用recur代替,在该循环中,它将读取通道,并在每次成功读取后返回以再次读取它。 如果发生超时,它将终止执行。

我有两个问题:
-这是正确的方法吗?
-如何使用惯用的Clojure实施

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(defn -main [& args]
  (let [c (async/chan)]
    (doseq [i (range 10)]
      (async/go
        (doseq [j (range 10)]
          (Thread/sleep (rand-int 1000))
          (async/>! c (str i" ::" j)))))
    (while  true
    (async/<!!
      (async/go
        (let [[result source] (async/alts! [c (async/timeout 500)])]
          (if (= source c)
            (println"Got a value!" result)
            (println"Timeout!"))))))))


这是一种非常常见的方法,因此回答第一个问题,我会说"是"。 core.async提供了一些便利,可能会使它变得更加像偶像了(尽管实际上是这样):

  • 优先于(go (while true ...))(go (loop ...))使用go-loop
  • 优先于(let [[result channel]] (alts! ...))使用alt!