Last active
February 13, 2016 20:06
-
-
Save ataggart/377278 to your computer and use it in GitHub Desktop.
This file contains 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
(defmacro try-let | |
"Behaves like try except the symbols in bindings are available to the catch | |
and finally clauses. The bindings' values are evaluated sequentially. If an | |
exception is thrown while evaluating a binding value, it and every subsequent | |
binding value will be nil. The catch clauses handle exceptions thrown by the | |
body of the try and by the evaluation of binding values. | |
Example: | |
(try-let [conn (API/openConnection)] | |
(do-stuff conn) | |
(finally (if conn (close conn)))" | |
{:arglists '([[bindings*] try-expr* catch-clause* finally-clause?])} | |
[bindings & exprs] | |
(let [ts (gensym) | |
names# (take-nth 2 bindings) | |
valex# (take-nth 2 (drop 1 bindings)) | |
[body# cf#] (split-with #(not (#{'catch 'finally} (first %))) exprs)] | |
`(let [~ts nil | |
~@(interleave names# (repeat nil)) | |
~@(interleave | |
(map vector names# (repeat ts)) | |
(for [v valex#] | |
`(if ~ts [nil ~ts] | |
(try [~v nil] | |
(catch Throwable t# [nil t#])))))] | |
(try | |
(if ~ts | |
(throw ~ts) | |
(do ~@body#)) | |
~@cf#)))) | |
(comment | |
; turns this: | |
(try-let [a (somefn x) b (somefn y) c (somefn z)] | |
(do-stuff a b c) | |
(catch MyException e (println a b c))) | |
; into something like this (where t is a gensym): | |
(let [t nil ; holds the exception thrown when evaluating binding values | |
a nil | |
b nil | |
c nil | |
[a t] (if t [nil t] (try [(somefn x) nil] (catch Throwable t [nil t]))) | |
[b t] (if t [nil t] (try [(somefn y) nil] (catch Throwable t [nil t]))) | |
[c t] (if t [nil t] (try [(somefn z) nil] (catch Throwable t [nil t])))] | |
(try | |
(if t | |
(throw t) | |
(dostuff a b c)) | |
(catch MyException e (println a b c)))) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment