Fork me on GitHub
#core-async
<
2018-01-24
>
hlship18:01:38

I end up writing a lot of code that consumes a channel using a go loop. I've created a useful macro:

(defmacro go-while
  "Accepts a single binding vector, and executes its body
  so long as the channel that is bound produces a value.

  The binding is standard binding vector of symbol and
  a channel to read from (the source).  The local symbol
  will be bound to successive values taken from the source.
  The source expression is evaluated only once.

  Evaluates to a channel that is closed once the loop completes
  (that is, when the source channel closes)."
  [binding & body]
  (let [[sym source] binding]
    `(let [port# ~source]
       (go-loop []
         (when-some [~sym (<! port#)]
           ~@body
           (recur))))))

(s/fdef go-while
  :args (s/cat :bindings (s/and vector? ::specs/binding)
               :body (s/* any?)))
This seems like a reasonable contribution to core.async, is it worth putting together a PR? If not, well, here it is, under ASL 2.0.