recur from catch
Clojure's recur function can only occur in a tail position. However, this does not work directly when using a loop/recur to repeat a possibly failing operation.
In this case, wrap the operation in a thunk, and return the value in a tuple of [result exception], where either the result or the exception is set (that's XOR). Then a simple 'if' can be used to determine if a result is returned or another attempt should be made.
A function that takes a thunk and a number of tries looks like this:
(defn try-loop [thunk tries]
(loop [n tries ex nil]
(if (zero? n)
(and ex (throw ex))
(let [[result exception] (try
[(thunk) nil]
(catch Throwable t
[nil t]))]
(if-not exception
result
(recur (dec n) (or ex exception)))))))
Comments on this:
- (if (zero? n) - tests if the retries count has finished.
- (and ex (throw ex)) - only throw ex if not nil.
- (recur (dec n) (or ex exception)) - the "(or ex exception)" is used to keep the first exception, instead of the last.
Written by Paul Gearon
Related protips
Have a fresh tip? Share with Coderwall community!
Post
Post a tip
Best
#Clojure
Authors
Sponsored by #native_company# — Learn More
#native_title#
#native_desc#