1

也许可以使用(<! c)宏及其宏扩展时间来完成使用外部宏的可能解决方案:

这是我的例子:

(ns fourclojure.asynco
      (require [clojure.core.async :as async :refer :all]))

(defmacro runtime--fn [the-fn the-value]
  `(~the-fn ~the-value)
  )
(defmacro call-fn [ the-fn]
  `(runtime--fn ~the-fn (<! my-chan))
  )

(def my-chan (chan))

(defn  read-channel [the-fn]
  (go
  (loop []
    (call-fn the-fn)
    (recur)
    )
  ))

(defn paint []
  (put! my-chan "paint!")
  )

并对其进行测试:

(read-channel print)
(repeatedly 50 paint)

我已经在嵌套中尝试过这个解决方案并且也可以工作。但我不确定它是否是正确的路径

这个问题的原因与另一个问题有关core.async 是否违反了 Clojure 原则?,@aeuhuea 评论说:“在我看来,这阻碍了简单性和可组合性。为什么这不是问题?” 和@cgrand 响应“go 宏(它的局部性)的限制也是一个特性:它强制执行有状态操作的源代码局部性。” 但是强制本地化您的代码与“完成”不同吗?

4

1 回答 1

6

关于你的问题的标题:

>!必须在 go 块中调用,因为它的设计目的是。如果您对 go-block 状态机机制感兴趣,我可以强烈推荐该http://www.youtube.com/channel/UCLxWPHbkxjR-G-y6CVoEHOw上的 Timothy Baldridges Youtube 视频

请记住,总是有阻塞的 take 和 put>!!<!!。我不知道您的代码的哪一部分应该为无法使用<!>!在 go 块之外提供“解决方案”,但是循环从单个通道调度的事件是常见的做法。这是读取通道的修改版本

(defn do-channel [f ch]
  (go-loop []
    (when-let [v (<! ch)]
      (f v)
      (recur))))

放!异步放置,这是您通常不想要的效果。在您的示例中,要将字符串“paint”放入通道 50 次,我建议使用这样的单行:

(do-channel println (to-chan (repeat 50 "print")))

这是对您编辑的回答的评论:通道并非旨在用作可变数据结构,时期。他们有一个缓冲区,这个缓冲区可以被认为是一个可变队列。但是,我们不使用通道在其中存储值,只是稍后再将其取出几行。我们使用通道作为帮助结构,可用于在两个或多个不同的位置执行两个或多个不同的源代码。例如,这里的 go-block 在收到另一个 go-block 生成的值之前不会继续执行。>!>!!帮助我们区分它们是在线程阻塞上下文中使用还是在 go-block(阻塞衍生进程)中使用。

另外,请参考这个答案:Clojure - 为什么在阻塞插入通道时执行挂起?(core.async)

你不应该在 go-block 中使用>!!or <!!,既不透明也不嵌套在函数调用中。Rich Hickey 本人在最近的错误报告(http://dev.clojure.org/jira/browse/ASYNC-29?focusedCommentId=32414&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel #comment-32414)。

查看您的源代码>!会发现它只会引发异常。事实上,go将替换>!为不同的源代码。go产生一个状态机控制的进程。根据上下文,您可能希望明确地知道这一点或将 go 块嵌套在宏或函数中(如您提供的代码示例中)。

关于 David Nolens (swannodettes) 助手:它们已由 Rich Hickey 和 Nolen 自己实现到 core.async 库中。Nolen 自己说,他们在此演示文稿中被取代(http://www.youtube.com/watch?v=AhxcGGeh5ho)。请注意,go-loop自 Nolens 提交后已实施。

于 2013-10-23T13:29:09.247 回答