【问题标题】:Why "Assert failed: >! used not in (go ...) block"为什么“断言失败:>!未在(go ...)块中使用”
【发布时间】:2017-08-31 00:56:25
【问题描述】:

我试图在我的 REPL 中找出 core.async 并且对于我对 (go-loop ...) 的使用如何不符合异步目的的“go block”资格感到完全困惑/>!

我的 go-loop 就像......

(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) 调用?

我什至应该在这里使用 go-loop 吗?

【问题讨论】:

  • @OlegTheCat 答案可能是一样的,但不是完全相同的问题。就像 2 + 5 = 7 和 8 - 1 = 7 并不是同一个问题,即使答案相同。换句话说,如果一个人非常熟悉 core.async 这可能看起来像同一个问题,但对于新人来说......说谷歌搜索那个异常消息,你在寻找这个异常消息时不会遇到那个 Clojurescript 问题。

标签: clojure core.async


【解决方案1】:

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

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

来自Clojure.Asyncs Github best practice page

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

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

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

这是要记住的一件事,因为许多 Clo​​jure 构造在宏内部创建函数。以下是无法按预期工作的代码示例:

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

【讨论】:

  • so...(do-seq... 而不是 (dorun (map... 尝试会让我摆脱嵌套函数异常?你可能已经猜到了……我对 core.async 有点陌生。
  • @BobKuhar 阅读新的更新。找到了官方来源。请注意,许多宏会产生函数,因此也可能无法节省您的时间。
  • 是的...(doseq [row page] ... 克服了嵌套函数的问题并且工作得非常好。谢谢
  • 根据您的帮助请求,我将代码块移到了引用的块中。我认为我做对了,但请随时验证。作为参考,您只需将&gt; (那里有一个尾随空格)添加到代码块的行首即可。
  • @NathanDavis 啊。谢谢。这样看起来好多了。
猜你喜欢
  • 1970-01-01
  • 2013-09-06
  • 2019-08-14
  • 2019-01-19
  • 2020-12-30
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 2019-06-03
相关资源
最近更新 更多