Я в гл. 6 из 7 моделей параллелизма Пола Мясника за 7 недель , которые фокусируются на core.async
.
У нас есть следующая функция
(defn map-chan [f from]
(let [to (chan)]
(go-loop []
(when-let [x (<! from)]
(>! to (f x))
(println "parking channel write.")
(recur))
(close! to))
(println "map-chan done.")
to))
Я добавил printlns
Я сам, чтобы выяснить точный порядок вычислений, о котором я хочу спросить здесь.
Мы можем запустить его так:
(def ch (to-chan (range 10))) ; [1]
(def mapped (map-chan (partial * 2) ch)) ; [2]
(<!! (async/into [] mapped)) ; [3]
;; [1] Create & rtn a channel from els of seq, closing it when seq fin.
;; [2] map-chan returns immediately, with blocked go blocks inside of it.
;; [3] calling async/into finally triggers the parked channel writes, as seen below.
в ответе:
channels.core=> (def ch (to-chan (range 10)))
#'channels.core/ch
channels.core=> (def mapped (map-chan (partial * 2) ch))
map-chan done.
#'channels.core/mapped
channels.core=> (<!! (async/into [] mapped))
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
parking channel write.
[0 2 4 6 8 10 12 14 16 18]
channels.core=>
Вопрос
У нас есть (syn c) (то есть небуферизованный) канал, который имеет и писатель, и читатель, готовый к go. Почему моя "запись канала парковки" выше не запускается до тех пор, пока не будет вызван async/into
? (Это не канал, прочитанный с помощью <!!
, который запускает его, а сам async/into
- это легко проверить). Я не жалуюсь на это, просто пытаюсь понять, почему след таков. Действительно ли каналы ленивы? Он еще не упомянул об этом в книге.
Обратите внимание, что зависимость от этого кода равна org.clojure/core.async "0.1.267.0-0d7780-alpha"
, если это имеет какое-то значение.
Кроме того, в книге он использовал буферизованный канал длины 10. Тем не менее, я также попробовал его с небуферизованным (syn c) каналом, и результат кажется тем же.