Skip to content

Instantly share code, notes, and snippets.

@paxan
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paxan/9017097 to your computer and use it in GitHub Desktop.
Save paxan/9017097 to your computer and use it in GitHub Desktop.
with-open-seq
(require '[clojure.core.async :refer [chan close! go >! <!!]])
(defmacro with-open-seq
"Like with-open, but only closes resources when
the sequence generated by the body is exhausted."
[bindings & body]
`(let [c# (chan)]
(go
(try
(with-open ~bindings
(doseq [i# (do ~@body)]
(>! c# (list i#))))
(catch Exception e#
(>! c# e#))
(finally
(close! c#))))
(map first
(take-while (complement nil?)
(repeatedly
#(let [i# (<!! c#)]
(if (instance? Exception i#)
(throw i#)
i#)))))))
; demo:
(with-open
[foo (clojure.java.io/reader (char-array "foo\nqaz\n12345"))]
(line-seq foo))
;=> IOException Stream closed java.io.BufferedReader.ensureOpen (BufferedReader.java:115)
(with-open-seq
[foo (clojure.java.io/reader (char-array "foo\nqaz\n12345"))]
(line-seq foo))
;=> ("foo" "qaz" "12345")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment