我刚注意到pipeline
系列返回了一个channel
,它似乎完全独立于管道及其相关渠道的目的而运作。
请注意,在以下示例中,您可以>! / <!
和pipes
分别a> / b>
,而且它们无关。
据我了解,pipeline
应为无操作,并在设置nil
从transduc
到{{1}的副作用时返回a>
}}
那么,我错过了什么,为什么b>
会返回pipeline
?
channel
答案 0 :(得分:8)
当没有更多要复制的元素时,您将返回一个已关闭的频道。也就是说,在a>
关闭后,其中的所有元素都已大写并放在b>
上。你可以从结果通道<!
找出流水线操作何时完成,如果你在意,或者你可以扔掉通道。你可能不应该写信。
这是许多异步操作的常见模式,实际上经常会隐式发生:每个go
块返回一个通道,当块完成时,该通道会将块的返回值写入其中,并且许多异步操作使用一个go
块作为返回值,因此您可以自动获得此“完成工作”的通道。
答案 1 :(得分:3)
要解释@ amalloy的答案,在以下示例中,a>
和b>
在能够完成时会将true
置于其上。由于chan>
是无缓冲的,因此在另一个进程取消它们之前无法完成,即最后的println
。
如果chan>
被缓冲,a>
和b>
可以立即>!
,所以立即打印。
(def chan> (chan 4))
(def a> (go (>! chan> "Apple")))
(go (println "from a>: " (<! a>)))
(def b> (go (>! chan> "Ball")))
(go (println "from b>: " (<! b>)))
(go (println "from chan>: "(<! chan>)))
;; => from chan>: Apple
;; => from a>: true
(go (println "from chan>: "(<! chan>)))
;; => from chan>: Ball
;; => from b>: true
这与pipeline
s背后的想法相同。
;; Pipeline-specific
(def a> (chan))
(def b> (chan))
(def p> (pipeline 4 b> (map clojure.string/upper-case) a>))
;; this won't happen until `a>` `close!`s
(go (println "pipeline is done: " (<! p>)))
;; execute the following 2 lines ad lib
(go (>! a> "hi there"))
(go (println "from b>: " (<! b>)))
(comment
(close! a>) ; triggers the "pipeline is done"
(close! b>)) ; doesn't trigger it, but `b>` now only returns nil when taking