使用隐式类时,未正确调用Scala Future

时间:2017-03-20 19:48:14

标签: scala future

我想调整这个example

def retry[T](f: => Future[T], delays: Seq[FiniteDuration])(implicit ec: ExecutionContext, s: Scheduler): Future[T] = {
  f recoverWith { case _ if delays.nonEmpty => after(delays.head, s)(retry(f, delays.tail) }
}

支持以下呼叫:myFuture.retry(Seq(1.seconds, 5.seconds, 10.seconds)).map {data => process(data)}

以下是我实施它的方式:

import akka.pattern.after
import akka.actor.Scheduler
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.duration.FiniteDuration

object FutureExtension {

  implicit class FutureExtension[T](f: Future[T]) {

    def retry(delays: Seq[FiniteDuration])(implicit ec: ExecutionContext, s: Scheduler): Future[T] = {
      f recoverWith { case _ if delays.nonEmpty => after(delays.head, s)(f.retry(delays.tail)) }
    }

  }

}

我注意到retry方法被正确调用,但它没有评估原始未来。在调试时,我注意到未来的值是Failure,我想这表明我永远无法正常恢复,这意味着我永远不会称之为原始未来。

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

这里的关键点是,Future是按值调用的,而示例Future是按名称调用的,{{1}表示在它的类型之前。

在调用函数之前,将按值调用参数(scala default)计算一次,然后将其视为=>

在函数调用之前不会对按名称调用的参数(使用val类型定义)进行求值,而是将其作为" thunk",它将在每次执行时执行在函数内部调用。这与=> T

相同

事实证明,您可以使用call-by-name参数创建一个隐式类,因此您只需在类参数中添加双箭头def即可获得所需内容。