Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Short-circuiting logical disjunction of several futures' results in core.async
(defn thread-or
"Call each of the fs on a separate thread. Return logical
disjunction of the results. Short-circuit (and cancel the calls to
remaining fs) on first truthy value returned."
[& fs]
(let [futs-and-cs
(doall (for [f fs]
(let [c (chan)]
[(future (>!! c (f))) c])))]
(loop [futs-and-cs futs-and-cs]
(let [[result c] (alts!! (map peek futs-and-cs))]
(if result
(do (doseq [fut (map first futs-and-cs)]
(future-cancel fut))
result)
(let [new-futs-and-cs (remove #(identical? (peek %) c)
futs-and-cs)]
(if (next new-futs-and-cs)
(recur new-futs-and-cs)
(<!! (peek (first new-futs-and-cs))))))))))
(comment
(thread-or (constantly true) (constantly true))
;;= true
(thread-or (constantly true) (constantly false))
;;= true
(thread-or (constantly false) (constantly false))
;;= false
;; prints :foo before returning true
(thread-or #(do (Thread/sleep 3000) true)
#(do (Thread/sleep 1000) (println :foo)))
;; does not print :foo
(thread-or #(do (Thread/sleep 3000) true)
#(do (Thread/sleep 7000) (println :foo)))
)
@michalmarczyk

This comment has been minimized.

Copy link
Owner Author

michalmarczyk commented Jul 12, 2013

Written in reponse to the Short-circuiting futures in clojure Stack Overflow question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.