使用隐式 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]
争论得到你想要的。
我想改编这个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]
争论得到你想要的。