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
; Released under the Apache License, Version 2.0 | |
; http://www.apache.org/licenses/LICENSE-2.0.html | |
(defmacro try-let | |
"A combination of try and let such that exceptions thrown in the binding or | |
body can be handled by catch clauses in the body, and all bindings are | |
available to the catch and finally clauses. If an exception is thrown while | |
evaluating a binding value, it and all subsequent binding values will be nil. | |
Example: | |
(try-let [x (f a) | |
y (f b)] | |
(g x y) | |
(catch Exception e (println a b x y e)))" | |
{:arglists '([[bindings*] exprs* catch-clauses* finally-clause?])} | |
[bindings & exprs] | |
(when-not (even? (count bindings)) | |
(throw (IllegalArgumentException. "try-let requires an even number of forms in binding vector"))) | |
(let [names (take-nth 2 bindings) | |
values (take-nth 2 (next bindings)) | |
ex (gensym "ex__")] | |
`(let [~ex nil | |
~@(interleave names (repeat nil)) | |
~@(interleave | |
(map vector names (repeat ex)) | |
(for [v values] | |
`(if ~ex | |
[nil ~ex] | |
(try [~v nil] | |
(catch Throwable ~ex [nil ~ex])))))] | |
(try | |
(when ~ex (throw ~ex)) | |
~@exprs)))) | |
(comment | |
; turns this: | |
(try-let [x (f a) | |
y (f b)] | |
(g x y) | |
(catch Exception e (println a b x y e))) | |
; into something like this (where ex is a gensym): | |
(let [ex nil ; holds the exception thrown when evaluating binding values | |
x nil | |
y nil | |
[x ex] (if ex [nil ex] (try [(f a) nil] (catch Throwable ex [nil ex]))) | |
[y ex] (if ex [nil ex] (try [(f b) nil] (catch Throwable ex [nil ex])))] | |
(try | |
(when ex (throw ex)) | |
(g x y) | |
(catch Exception e (println a b x y e)))) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment