Как создать канал из другого с преобразователями?

Я хочу создать канал clojure.core.async из другого, который просто фильтрует определенные сообщения. Поэтому я нашел функцию под названием filter‹.

=> (def c1 (chan))
=> (def c2 (filter< even? c1))
=> (put! c1 1)
=> (put! c1 2)
=> (<!! c2)
2

Но функция и ее друзья помечены как устаревшие:

Устарело - эта функция будет удалена. Вместо этого используйте преобразователь

Есть несколько способов использовать каналы с преобразователем типа chan с параметром xform. Как я могу построить новый канал из существующего с помощью преобразователей?


person sschmeck    schedule 08.07.2015    source источник


Ответы (1)


Я провел небольшое исследование по этому вопросу и нашел несколько интересных статей (первой и секунду), а затем что-то заработало, используя pipeline

(require '[clojure.core.async :as async :refer [chan <!! pipeline put!]])
(def c1 (chan))
(def c2 (chan))

(pipeline 4 c2 (filter even?) c1)

(put! c1 1)
(put! c1 2)
(<!! c2)
;;=> 2

Вторая статья, на которую я ссылаюсь, делает это немного чище с некоторыми вспомогательными функциями вокруг функции конвейера:

(defn ncpus []
  (.availableProcessors (Runtime/getRuntime)))

(defn parallelism []
  (+ (ncpus) 1))

(defn add-transducer
  [in xf]
  (let [out (chan (buffer 16))]
    (pipeline (parallelism) out xf in)
    out))

Затем вы можете просто связать каналы вместе с

(def c1 (chan))
(def c2 (add-transducer c1 (filter even?))

Чтобы завершить ответ, как вы обнаружили, вы можете использовать трубу аналогичным образом:

(defn pipe-trans
  [ci xf]
  (let [co (chan 1 xf)]
    (pipe ci co)
    co))
(def c1 (chan))
(def c2 (pipe-trans c1 (filter even?)))
person Mark Fisher    schedule 08.07.2015
comment
Вдохновленный вами, я создал метод факори, используя pipe. (defn from-chan [ci xf] (let [co (chan 1 xf)] (pipe ci co) co)) - person sschmeck; 08.07.2015
comment
здорово, рад, что смог помочь. - person Mark Fisher; 08.07.2015
comment
я добавил версию вашего фабричного метода, чтобы попытаться завершить ответ на случай, если другие будут его искать. - person Mark Fisher; 08.07.2015
comment
Заметил это: dev.clojure.org/jira/browse/ASYNC-153 Похоже, что pipe-trans можно упростить до (defn pipe-trans [ci xf] (pipe ci (chan 1 xf))), но это недокументировано - person Lof; 23.01.2017