无法重载 Scala Implicit 中的 apply 方法 class
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 类
解决了它
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 编译器不允许 overload 只允许 implicit 类 中的 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
抛出异常,并且 async
会立即导致失败 Future
。所以在这个实现中,函数实际上并没有重试。
你需要这样的东西:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
此外,我认为,在 Futures 上定义此恢复方法可能更清晰:
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 }
我正在用 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 类
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 编译器不允许 overload 只允许 implicit 类 中的 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
抛出异常,并且 async
会立即导致失败 Future
。所以在这个实现中,函数实际上并没有重试。
你需要这样的东西:
def convertTriedFuture[T](f: => Future[T]): Future[Try[T]] =
f.map(Success.apply).recover { case e => Failure(e) }
此外,我认为,在 Futures 上定义此恢复方法可能更清晰:
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 }