为什么"断言失败:>!用于(go ...)block"

时间:2017-08-31 00:56:25

标签: clojure core.async

我试图弄清楚我的REPL中的core.async,并且完全混淆了我对(go-loop ...)的使用方式是如何设置为" go block&# 34;出于async />!

的目的

我的循环就像......

(async/go-loop [page (range 3)]
  (if (empty? page)
    (async/close! ch)
    (dorun (map (fn [row]
                  (println row)
                  (async/>! ch row)) page)))
  (recur (range (dec (count page)))))

但是REPL都很不高兴......

=>
#object[clojure.core.async.impl.channels.ManyToManyChannel
        0x23465937
        "clojure.core.async.impl.channels.ManyToManyChannel@23465937"]
0
Exception in thread "async-dispatch-12" java.lang.AssertionError: Assert failed: >! used not in (go ...) block
nil
...

为什么(go-loop ...)呼叫的范围不足(async/>! row)

我是否应该在这里使用循环?

1 个答案:

答案 0 :(得分:7)

不幸的是,<>!和其他停车调用无法在嵌套在go内的函数内使用。

go将您提供的代码转换为状态机并查找停车呼叫。但是它不会查看嵌套函数。

来自Clojure.Asyncs Github best practice page

  

go块中不支持的构造和其他限制

     

go宏停止在函数创建边界处进行转换。这意味着以下代码将无法编译,或者可能只是抛出一个运行时错误,指出在go块之外使用了<!

(go (let [my-fn (fn [] (<! c))]
    (my-fn)))
     

这是一件值得记住的事情,因为许多Clojure构造在宏内创建函数。以下是无法正常工作的代码示例:

(go (map <! some-chan))
(go (for [x xs]
      (<! x)))