Created
July 12, 2013 22:19
-
-
Save michalmarczyk/5988303 to your computer and use it in GitHub Desktop.
Short-circuiting logical disjunction of several futures' results in core.async
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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))) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Written in reponse to the Short-circuiting futures in clojure Stack Overflow question.