2016-11-07 17 views
4

Я только заметил, что семейство pipeline возвращает channel, который, по-видимому, полностью работает независимо от цели трубопровода и связанных с ним каналов.Почему «core.async/конвейер» возвращает канал?

Обратите внимание, что в следующем примере вы можете >!/<! от pipes и a>/b> отдельно, и они не связаны.

Насколько я понимаю, pipeline s должно быть не оп, и вернуться nil при настройке sideffecting transduc Тион от a> к b>.

Итак, что мне не хватает, и почему pipeline возвращает channel?

(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 блок возвращает канал, который имеет возвращаемое значение блока записывается в него, когда блок завершается, и многие асинхронные операции используют 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 

 Смежные вопросы

  • Нет связанных вопросов^_^