如何将代码块传递给函数?

时间:2014-01-16 18:25:18

标签: scala lambda functional-programming currying

我正在尝试创建一个 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

将自定义块传递给我的函数的最简洁方法是什么?

2 个答案:

答案 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

保留了最初建议的语义,但它提取了每次失败尝试的信息。