在抛出异常之前重试3次-Clojure [英] retrying something 3 times before throwing an exception - in clojure
问题描述
我不知道如何在Clojure中实现这段Python代码
I don't know how to implement this piece of Python code in Clojure
for i in range(3):
try:
......
except e:
if i == 2:
raise e
else:
continue
else:
break
我想知道为什么Python中这么简单的东西是如此在Clojure中很难。我认为困难在于,因为Clojure是一种功能编程语言,因此不适合执行这样的命令性任务。这是我的尝试:
I wonder why something so simple in Python is so hard in Clojure. I think the difficulty is because Clojure is a functional programming language and thus is not suitable for such an imperative task. This is my attempt:
(first
(remove #(instance? Exception %)
(for [i (range 3)]
(try (......)
(catch Exception e
(if (== i 2)
(throw e)
e)))))))
这很丑陋,更糟糕的是,它不能按预期工作。 for循环实际上是经过完全评估而不是懒惰地求值(当我将println放入其中时,我才意识到这一点。)
It is very ugly, and worse, it doesn't work as expected. The for loop is actually evaluated fully instead of lazily (I realized this when I put a println inside).
如果有人有更好的想法来实现,请启发我。
If anyone has a better idea to implement that, please enlighten me.
推荐答案
类似于Marcyk的答案,但没有宏观欺骗手段:
Similar to Marcyk's answer, but no macro trickery:
(defn retry
[retries f & args]
(let [res (try {:value (apply f args)}
(catch Exception e
(if (zero? retries)
(throw e)
{:exception e})))]
(if (:exception res)
(recur (dec retries) f args)
(:value res))))
有点复杂因为您不能在 catch
子句中重复
。请注意,该函数具有以下功能:
Slightly complicated because you can't recur
inside a catch
clause. Note that this takes a function:
(retry 3 (fn []
(println "foo")
(if (zero? (rand-int 2))
(throw (Exception. "foo"))
2)))
=>
foo ;; one or two or three of these
foo
2
这篇关于在抛出异常之前重试3次-Clojure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!