2
votes

With Clojure's Core.Async one can map over a channel by using transducers:

(def my-chan (chan (buffer 10) (map inc)))

But what happens if the mapper function itself is async?

Say, we have a:

(defn async-inc [n]
  (let [c (promise-chan)]
    (put! (inc n))
    c))

Is there a similar concise way to map the channel over this function? Or would one have to do something like this:

(def my-chan (chan (buffer 10)))
(def my-chan2 (chan (buffer 10)))

(go (while true
      (>! my-chan2
          (<! (async-inc (<! my-chan))))))

It would not really be mapping, since two channels are needed instead of one.

1

1 Answers

1
votes

There is a general advice not to create channel inside a function and return it out because it forces user of that function to use core.async. You can either return an output through a promise or return through callback function.

Assuming what you want to do with an output from async-inc is to print it out using println function.

Return through a promise

(defn async-inc [n]
  (let [p (promise)]
    (deliver p (inc n))
    p))

(println @(async-inc (<! my-chan)))

Return through callback

(defn async-inc [n callback]
  (callback (inc n)))

(async-inc (<! my-chan) println)

But if you don't have a control over async-inc. Here are your options.

Use <!!

(println (<!! (go (<! (async-inc (<! my-chan))))))

or

Use take!

(take! (go (<! (async-inc (<! my-chan)))) println)