[英]Can't overload apply method in Scala Implicit class
我正在使用async
和await
编写retry
功能
def awaitRetry[T](times: Int)(block: => Future[T]): Future[T] = async {
var i = 0
var result: Try[T] = Failure(new RuntimeException("failure"))
while (result.isFailure && i < times) {
result = await { Try(block) } // can't compile
i += 1
}
result.get
}
Scala编译器报告错误。 由于Try
没有应用方法,因此需要使用Future[T]
。 所以我用隐式类解决了
implicit class TryCompanionOps(val t: Try.type) extends AnyVal {
// can't use `apply`!
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(value => Try(value))
}
// now we can convert Future[T] into Future[Try[T]] e.g,
await { Try.convertTriedFuture(block) }
我的问题是
为什么不能使用名称apply
而不是convertTriedFuture
? 似乎scala编译器不允许仅重载 隐式类中的 apply
方法。
谢谢。
Scala仅在找不到具有所需签名的现有方法时才开始寻找隐式转换。 但是在Try
伴随对象中,已经有一个合适的方法: def apply[T](r: ⇒ T): Try[T]
,因此Scala apply
T
推断为Future[Something]
,并且不检查隐式转换。
另外,此实现将无法正常工作:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(value => Try(value))
如果Future
失败,则不会调用map
的函数,并且从await
抛出Exception,并且async
立即导致失败的Future
。 因此,使用此实现,该函数实际上不会重试。
您需要类似:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
另外,我认为,在期货中定义此恢复方法可能更简洁:
implicit class FutureAdditionalOps[T](f: Future[T]) {
def recoverError: Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
}
然后你可以
result = await { block.recoverError }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.