Up vote 8 down vote favorite 5 share g+ share fb share tw.
I am trying to execute a func several times before giving up upon exceptions. But it is not valid in Clojure to recur from catch block. How can this be achieved?
(loop tries 10 (try (might-throw-exception) (catch Exception e (when (pos? Tries) (recur (dec tries)))))) java.lang. UnsupportedOperationException: Cannot recur from catch/finally The best I could find is the following clumsy solution (wrapping in func and calling it) (defn do-it (try (might-throw-exception) (catch Exception e nil))) (loop times 10 (when (and (nil?
(do-it)) (pos? Times)) (recur (dec times)))) clojure link|improve this question edited Dec 13 '09 at 11:44Jonas5,52632033 asked Dec 10 '09 at 9:44GabiMe2,14931132 88% accept rate.
Macros are calling... How about this: (defn try-times* "Executes thunk. If an exception is thrown, will retry. At most n retries are done.
If still some exception is thrown it is bubbled upwards in the call chain. " n thunk (loop n n (if-let result (try (thunk) (catch Exception e (when (zero? N) (throw e)))) (result 0) (recur (dec n))))) (defmacro try-times "Executes body.
If an exception is thrown, will retry. At most n retries are done. If still some exception is thrown it is bubbled upwards in the call chain.
" n & body `(try-times* ~n (fn ~@body))).
This is a fine solution. I would add it to clojure. Contrib or something.
– GabiMe Dec 10 '09 at 10:26 It's actually the same solution as the one the poster suggested. But macros make it easier to do in the general case. Macros are the killer feature of any lisp variant.
– Jeremy Wall Dec 10 '09 at 18:17 It's not exactly the same solution. The poster's suggestion does not catch the return value of the block, and if it did the block wouldn't be able to return nil. Also the exceptions are swallowed.
But you are right: it's basically the same idea. Macros just hide the boilerplate. – kotarak Dec 10 '09 at 21:48.
Kotarak's idea is the way to go, but this question tickled my fancy so I'd like to provide a riff on the same theme that I prefer because it doesn't use loop/recur: (defn try-times* thunk times (let res (first (drop-while #{::fail} (repeatedly times #(try (thunk) (catch Throwable _ ::fail))))) (when-not (= ::fail res) res))) And leave the try-times macro as it is. If you want to allow the thunk to return nil, you can drop the let/when pair, and let ::fail represent "the function failed n times", while nil means "the function returned nil". This behavior would be more flexible but less convenient (the caller has to check for ::fail to see if it worked rather than just nil), so perhaps it would be best implemented as an optional second parameter: (defn try-times* thunk n & fail-value (first (drop-while #{fail-value} ...))).
1 for not using loop/recur. – rplevy Mar 9 '11 at 5:15.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.