【问题标题】:couldn't use for loop in go block of core.async?不能在 core.async 的 go 块中使用 for 循环?
【发布时间】:2014-11-20 08:45:41
【问题描述】:

我是 clojure core.async 库的新手,我正在尝试通过实验来理解它。

但是当我尝试时:

(let [i (async/chan)] (async/go (doall (for [r [1 2 3]] (async/>! i r)))))

它给了我一个非常奇怪的例外:

CompilerException java.lang.IllegalArgumentException: No method in multimethod '-item-to-ssa' for dispatch value: :fn

我尝试了另一个代码:

(let [i (async/chan)] (async/go (doseq [r [1 2 3]] (async/>! i r))))

它根本没有编译器异常。

我完全糊涂了。发生了什么?

【问题讨论】:

  • for 在 clojure 中 不是 循环 - 它是列表理解。考虑到这一点,您的 for 示例不是调用副作用 >! 函数的惯用方式。也许编译器消息可以/应该改进,但您的根本问题是以这种方式使用 for 没有(clojure)意义。 doseq 非常好。
  • >!块,它等待有人从频道读取。尝试先设置阅读部分,或者使用put!
  • @edbond 哇,这确实有效.. 但我更困惑,Timothy Baldridge 刚才不是说 async/go 不能在 async/go 块中处理 fn 吗?跨度>

标签: clojure core.async


【解决方案1】:

所以 Clojure go-block 在函数边界停止翻译,原因有很多,但最大的原因是简单。这在构建惰性序列时最常见:

(go (lazy-seq (<! c)))

被编译成这样的:

(go (clojure.lang.LazySeq. (fn [] (<! c))))

现在让我们快速思考一下……这应该返回什么?假设您可能想要的是一个包含取自 c 的值的惰性序列,但 &lt;! 需要将函数的剩余代码转换为回调,但 LazySeq 期望函数是同步的。确实没有办法绕过这个限制。

回到你的问题,如果你宏扩展for,你会发现它实际上并没有循环,而是扩展成一堆代码,最终调用lazy-seq,所以停车操作在里面不起作用身体。 doseq(和dotimes)但是得到loop/recur 的支持,所以这些都可以正常工作。

还有一些其他地方可能会让您感到不快,with-bindings 就是一个例子。基本上,如果宏将您的 core.async 停车操作粘贴到嵌套函数中,您将收到此错误。

我的建议是让你的 go 块的主体尽可能简单。写纯函数,然后把 go blocks 的 body 当作做 IO 的地方。

------------ 编辑 -------------

通过在函数边界处停止转换,我的意思是:go 块获取其主体并将其转换为状态机。对&lt;!&gt;!alts!(以及其他一些)的每次调用都被视为可以暂停块执行的状态机转换。在这些点中的每一个点,机器都会变成回调并附加到通道。当此宏到达 fn 表单时,它会停止翻译。所以你只能从 go 块内部调用&lt;!,而不是代码块内部的函数。

这是 core.async 魔力的一部分。如果没有 go 宏,core.async 代码在其他语言中看起来很像回调地狱。

【讨论】:

  • 你能解释一下stops translation at function boundaries是什么意思吗?
  • 添加到我原来的帖子中
  • 我明白了,所以也许 core.async 可以向 :fn 添加更多方法并抛出更好的异常。这对初学者很不友好。
  • 从评论中了解到,(let [i (async/chan)] (async/go (doall (for [r [1 2 3]] (async/put! i r)))) (async/go (println (async/&lt;! i)))) 确实有效,这与fn 不能出现在async/go 块中的想法不冲突吗?
  • 这是否意味着如果一个库(data.xml)想要一个序列,你就是 SOL?
猜你喜欢
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多