我正在尝试实现一个应该采用任意方法或代码块的方法,它应该将方法或代码块转换为可重试的方法。
以下示例旨在演示我需要的内容
import scala.util.{Try,Success,Failure}
object Retry {
retry[A, B](f: A => Try[B], r: Int): A => Try[B] = {
// return a function g and when g is invoked with parameters
// f should be tried (if failed) r number of time otherwise
// result of first successful execution of f should be returned
// from g. retry should work with any arbitrary function with
// any number/type of parameters
}
}
答案 0 :(得分:2)
如果你想抽象优于arity,这是非常先进的,你将不得不使用shapeless,一个用于泛型编程的库。
以@ chengpohi的答案为基础:
import shapeless._, ops.function._
import scala.util.Try
def retry[F, L <: HList, R](f: F, r: Int = 1)(implicit fnToP: FnToProduct.Aux[F, L => R], fnFromP: FnFromProduct.Aux[L => R, F]): F = {
val fn = fnToP(f)
def repeat(a: L): R = {
for (_ <- 0 to r) {
val tried = Try(fn(a))
if (tried.isSuccess) {
return tried.get
}
}
throw new RuntimeException(s"retry $r failed")
}
fnFromP(repeat _)
}
有效:
scala> var i = 0
i: Int = 0
scala> val f = retry( (a: Int) => if (i < 10) {i += 1; println(s"try $i"); throw new RuntimeException} else a * 3, 42)
f: Int => Int = shapeless.ops.FnFromProductInstances$$anon$2$$Lambda$1489/1404497488@1d49a23c
scala> f(5)
try 1
try 2
try 3
try 4
try 5
try 6
try 7
try 8
try 9
try 10
res4: Int = 15
scala> var i = 0
i: Int = 0
scala> val f = retry( (a: String, b: Int) => if (i < 10) {i += 1; println(s"try $i"); throw new RuntimeException} else a * b, 42)
f: (String, Int) => String = shapeless.ops.FnFromProductInstances$$anon$3$$Lambda$1492/121867201@1a22b89c
scala> f("foo", 5)
try 1
try 2
try 3
try 4
try 5
try 6
try 7
try 8
try 9
try 10
res5: String = foofoofoofoofoo
答案 1 :(得分:0)
def retry[A, B](f: A => B, r: Int = 1): A => B = {
def repeat(a: A): B = {
for (_ <- 0 to r) {
val tried = Try(f(a))
if (tried.isSuccess) {
return tried.get
}
}
throw new RuntimeException(s"retry $r failed")
}
repeat
}
有一种简单的方法可以执行此操作,try
如果成功且返回,否则throw Exception