2016-11-07 3 views
4

pipelineファミリがchannelを返すことに気がつきました。これは一見パイプラインの目的とは完全に独立して動作し、関連するチャネルです。`core.async/pipeline`がチャネルを返すのはなぜですか?

次の例では、>!/<!pipesa>/b>に分かれていますが、それらは無関係です。

は、私の知る限り理解し、pipeline sが無操作することなく、a>からb>にsideffecting transducションの設定中nilを返す必要があります。

私は何が分かりません、なぜpipelinechannelを返しますか?

(def a> (chan)) 
(def b> (chan)) 
(def pipes (pipeline-blocking 4 
        b> 
        (map clojure.string/upper-case) 
        a>)) 
(go (>! pipes "hello world")) 
(go (println "Pipes: " (<! pipes))) 
(go (>! a> "apples are gooood")) 
(go (println "B: " (<! b>))) 

答えて

7

コピーする要素がなくなると閉じられるチャンネルが返されます。すなわち、a>が閉じられ、それからのすべての要素が大文字にされ、b>に配置された後。結果のチャネルから<!を実行して、パイプライン操作がいつ行われたかを知ることができます。気にしていれば、チャネルを放棄することもできます。あなたはおそらくそれに書き込むべきではありません。

これは、多くの非同期操作の一般的なパターンです。実際には、暗黙的に起こることがよくあります。ブロックが完了するとブロックの戻り値が書き込まれ、多くの非同期操作でブロックgo結果としてこの「ジョブ完了」チャンネルを自動的に取得します。

+0

。私の説明がオフであれば教えてください! –

2

@ 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の背後にある同じ考えです。理にかなって、私はあなたと一緒に答えとして掲示実験を、実行するのに十分な私を与えた


;; 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 
関連する問題