我正在尝试创建一个 try 子句模拟,如果在此代码块中发生异常,则会重复代码块。
def retry(attempts: Int)(func: Unit => Unit) {
var attempt = 0
while (attempt < attempts) {
attempt += 1
try {
func()
} catch {
case _: Throwable =>
}
}
throw new Exception()
}
我希望它可以像这样使用
retry(10) { // I would like to pass this block as function
val res = someNotReliableOp(); // <- exception may occur here
print(res)
}
但它不起作用:
Operations.scala:27: error: type mismatch;
found : Unit
required: Unit => Unit
print(res)
^
one error found
将自定义块传递给我的函数的最简洁方法是什么?
答案 0 :(得分:8)
您只需稍微更改方法定义:
def retry(attempts: Int)(func: => Unit)
Unit => Unit
表示:一个函数,它接受类型为Unit
的参数并计算为Unit
。
=> Unit
表示:一个不带参数且计算结果为Unit
的函数。这称为call by name。
答案 1 :(得分:1)
考虑
def retry(attempts: Int)(func: => Unit) {
for {
i <- Stream range (0, attempts)
v = Try (func()) toOption
if (v == None)
} ()
}
for comprehension将调用func
最多attempts
次,如果调用func
成功,即Try(func) toOption
未传递{ {1}}。
对于for comprehension中的每次迭代,都会调用do-nothing None
函数。
如果对()
的每次失败的详细信息感兴趣,请考虑用
func
Try
保留了最初建议的语义,但它提取了每次失败尝试的信息。