这段代码在Clojure.core.async中做什么?

时间:2019-04-17 06:19:58

标签: clojure

这是The Beauty of Clojure的一段代码,我不明白 alt! 在这里做什么。

(defn listener [f ch]
  (let [stop-ch (chan)]
    (go-loop []
             (alt!
               stop-ch ([_] :no-op)
               ch      ([msg] (f msg) 
                              (recur))))
    {:listener ch :stop stop-ch}))

(defn stop-listener [{:keys [stop]}]
  (put! stop :stop))

尤其是 alt! 的第二个参数是什么:

ch     ([msg] (f msg)
              (recur))

是吗?

go-loop 意味着在调用 listener 函数后,它将无限期等待接收值吗?

1 个答案:

答案 0 :(得分:0)

转到循环alt!将执行哪个块,具体取决于哪个通道有消息。

您会注意到stop-ch不会再次发生,因此在收到停止指令后,go循环将结束。

如果在侦听器通道上接收到某些内容,则由功能f处理。然后,递归将我们带回到go循环的起点,在这里alt!将在侦听器或停止通道上等待其他消息。

创建的侦听器结构是两个通道的映射-将事物放入侦听器中,它们将被放置,将所有内容放置在停靠点上,然后侦听器将停止。然后,最终侦听器fn为用户抽象出最后的细节。

从本质上讲,这整个过程只是core.async通道和函数之间的一个简单适配器,带有清理逻辑。

go循环是否意味着在调用侦听器函数后它将无限期等待接收值?

不。呼叫侦听器不会阻止控制流。但是,创建的go循环将“阻塞”,直到在一个通道上接收到输入为止。我使用引号是因为这不是一个受阻碍的话题-我真的建议您在REPL上玩过后,看看一些基本的core.async演示文稿。一旦将行为与理论联系起来,就很简单了。