在抛出异常之前重试3次-Clojure [英] retrying something 3 times before throwing an exception - in clojure

查看:324
本文介绍了在抛出异常之前重试3次-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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆