wrapping around generic callback function with different signatures
我正在努力学习scala,到目前为止它似乎是一种非常强大的语言,但有些事情似乎很难实现,可能只是我的学习曲线。我在网上研究了几天,但找不到一个好的解决方案来做我想做的事情。
我有多个方法(具有不同的签名,包括返回类型),我希望用重试逻辑包装这些方法。
我想在方法成功之前,一直按预先定义的次数调用一个方法。
下面是一个例子:
1 2 3 4 5 |
我想在重试逻辑中包装这两个方法。下面是我对重试逻辑的尝试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
我遇到的问题是,在重试逻辑中找不到一种清晰的方法来包装我的方法(
有什么建议/想法吗?
您只需定义一个通用函数:
1 2 3 4 5 6 7 8 9 10 11 12 | import scala.util.{Try, Success, Failure} def retry[T](times: Int)(block: => T): T = Try(block) match { case Success(result) => result case Failure(e) => if (times > 0) { logger.warn(s"method failed with an exception, retry #$times") logger.warn(exception) retry(times - 1)(block) } else throw e } |
这是一个尾部递归函数,因此它与调用Java中的for循环中的函数一样有效。
然而,更惯用的scala将返回
1 2 3 4 5 6 7 8 | def retry2[T](times: Int)(block: => T): Try[T] = Try(block) match { case Failure(e) if (times > 0) => logger.warn(s"method failed with an exception, retry #$times") logger.warn(exception) retry2(times - 1)(block) case other => other } |
两个版本都可以用作:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def failRandomly: Int = if (scala.util.Random.nextInt < 0.80) throw new Exception("boom") else 1 scala> retry(2)(failRandomly) res0: Int = 1 scala> retry(2)(failRandomly) java.lang.Exception: boom // ... scala> retry2(2)(failRandomly) res1: scala.util.Try[Int] = Success(1) scala> retry2(2)(failRandomly) res2: scala.util.Try[Int] = Failure(java.lang.Exception: boom) |