clojure.async: "<! not in (go ...) block" 错误

clojure.async: "<! not in (go ...) block" error

当我评估以下 core.async clojurescript 代码时出现错误:"Uncaught Error: <! used not in (go ...) block"

(let [chans [(chan)]]
  (go
   (doall (for [c chans]
     (let [x (<! c)]
       x)))))

我在这里做错了什么?它绝对看起来像

因为 go 块不能跨越函数边界,所以在很多情况下我倾向于使用 loop/recur。 (go (loop 模式非常常见,它在 core.async 中有一个简写形式,在这种情况下很有用:

user> (require '[clojure.core.async :as async])
user> (async/<!! (let [chans [(async/chan) (async/chan) (async/chan)]]
                   (doseq [c chans]
                     (async/go (async/>! c 42)))
                   (async/go-loop [[f & r] chans result []]
                     (if f
                       (recur r (conj result (async/<! f)))
                       result))))
[42 42 42]

为什么不使用 Core.Async 中的 alts!

此功能可让您收听多个频道并知道您从哪个频道读取每个数据。

例如:

(let [chans [(chan)]]
  (go
    (let [[data ch] (alts! chans)]
        data)))))

你也可以问频道来源:

...
(let [slow-chan (chan)
      fast-chan (chan)
      [data ch] (alts! [slow-chan fast-chan])]
    (when (= ch slow-chan)
       ...))

来自文档:

Completes at most one of several channel operations. Must be called inside a (go ...) block. ports is a vector of channel endpoints, which can be either a channel to take from or a vector of [channel-to-put-to val-to-put], in any combination. Takes will be made as if by !. Unless the :priority option is true, if more than one port operation is ready a non-deterministic choice will be made. If no operation is ready and a :default value is supplied, [default-val :default] will be returned, otherwise alts! will park until the first operation to become ready completes. Returns [val port] of the completed operation, where val is the value taken for takes, and a boolean (true unless already closed, as per put!) for put

证明ref