Howdy --

Trying to use core.async's mix facility, one difficulty I've run into is 
the lack of a means to close the output channel only after al inputs have 
been exhausted. In the interim, I've ended up using the below instead -- 
which lacks some of the facilities provided by the mix interface (muting, 
pausing, soloing, etc), but has the advantage of cleanly closing its output 
channel if and only if all inputs (including the channel from which other 
channels are read) have been flushed.

That said, looking at core.async's code, it certainly seems possible to 
extend the mix abstraction to handle this use case -- for instance, adding 
a (close-on-empty! [mix]) call which would set a flag causing the the 
output channel to close whenever all inputs are unmixed, whether by user 
interaction or end-of-input, would be another solution.

Thoughts? Should I publish the below (and related tooling -- such as an 
N-way split helper used to create such channels of channels) as a separate 
library? Submit patches to core.async adding appropriate functionality to 
the mix implementation? Or is there already a better way of achieving the 
desired effect?

Thanks!

(defn merge-channels
  "Given a channel which yields other channels, combine output from all of 
these into a single output channel.

  Close output channel and exit when both the input channel and all 
channels read from that channel have closed."
  [in-chan]
  (let [out-chan (chan)]
    (go
      (loop [open-channels #{}, in-chan-open? true]
        (let [all-chans (if in-chan-open?
                          (conj open-channels in-chan)
                          open-channels)
              [v c] (when-not (empty? all-chans) (alts! (vec all-chans)))]
          (cond

           (empty? all-chans)
           nil

           (= c in-chan)
           (if v
             (recur (conj open-channels v) true)
             (recur open-channels false))

           (nil? v)
           (do
             (recur (disj open-channels c) in-chan-open?))

           :else
           (do
             (>! out-chan v)
             (recur open-channels in-chan-open?))))))
    out-chan))

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to