递归+ 一流的功能 ,按名称参数==很棒。
def retry[T](n: Int)(fn: => T): T = { try { fn } catch { case e => if (n > 1) retry(n - 1)(fn) else throw e }}用法是这样的:
retry(3) { // insert pre that may fail here}编辑
:受@themel的答案启发而略有变化。少一行代码:-)
def retry[T](n: Int)(fn: => T): T = { try { fn } catch { case e if n > 1 => retry(n - 1)(fn) }}再次编辑
:递归使我感到困扰,因为它向堆栈跟踪添加了多个调用。由于某些原因,编译器无法在catch处理程序中优化尾部递归。但是,尾部递归不在catch处理程序中,可以很好地优化:-)
@annotation.tailrecdef retry[T](n: Int)(fn: => T): T = { val r = try { Some(fn) } catch { case e: Exception if n > 1 => None } r match { case Some(x) => x case None => retry(n - 1)(fn) }}再次编辑
:显然,我将把它作为一种爱好,不断回来并为此答案添加替代方法。这是一个尾递归版本,它比使用更加简单
Option,但是使用
return短路功能并不是惯用的Scala。
@annotation.tailrecdef retry[T](n: Int)(fn: => T): T = { try { return fn } catch { case e if n > 1 => // ignore } retry(n - 1)(fn)}Scala 2.10更新 。作为我的业余爱好,我偶尔会重新审视此答案。Try引入的Scala 2.10
提供了一种以尾递归方式实现重试的干净方法。
// Returning T, throwing the exception on failure@annotation.tailrecdef retry[T](n: Int)(fn: => T): T = { util.Try { fn } match { case util.Success(x) => x case _ if n > 1 => retry(n - 1)(fn) case util.Failure(e) => throw e }}// Returning a Try[T] wrapper@annotation.tailrecdef retry[T](n: Int)(fn: => T): util.Try[T] = { util.Try { fn } match { case util.Failure(_) if n > 1 => retry(n - 1)(fn) case fn => fn }}


