使用隐式 class 时未正确调用 Scala Future

Scala Future is not properly called when using implicit class

我想改编这个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 方法被正确调用,但它没有计算原始 future。调试时,我注意到 future 的值为 Failure,我想这表明我永远无法正确恢复,这意味着我永远不会调用原始 future。

我该如何解决这个问题?

这里的关键点是您的 Future 是按值调用,而示例的 Future 是按名称调用,如前面的 => 所示它的类型。

按值调用参数(scala 默认值)在函数被调用之前计算一次,然后被视为 val

按名称调用的参数(用 => T 类型定义)在函数调用之前不会被评估,而是作为 "thunk" 给出,每次调用时都会执行在函数里面。这与 def.

相同

事实证明,您可以创建一个带有按名称调用参数的隐式 class,因此您只需在 class 中添加双箭头 f: => Future[T]争论得到你想要的。