【发布时间】:2019-05-14 12:44:50
【问题描述】:
Scala 标准库中是否有从Either 到Try 的任何转换?也许我遗漏了一些东西,但我没有找到它们。
【问题讨论】:
标签: scala
Scala 标准库中是否有从Either 到Try 的任何转换?也许我遗漏了一些东西,但我没有找到它们。
【问题讨论】:
标签: scala
据我所知,这在标准库中不存在。尽管Either 通常与Left 失败和Right 成功一起使用,但它实际上旨在支持两种可能的返回类型的概念,其中一种不一定是失败情况。我猜这些人们期望存在的转换并不存在,因为Either 并没有真正设计为像Try 这样的成功/失败单子。话虽如此,自己丰富Either 并添加这些转换非常容易。这可能看起来像这样:
object MyExtensions {
implicit class RichEither[L <: Throwable,R](e:Either[L,R]){
def toTry:Try[R] = e.fold(Failure(_), Success(_))
}
implicit class RichTry[T](t:Try[T]){
def toEither:Either[Throwable,T] = t.transform(s => Success(Right(s)), f => Success(Left(f))).get
}
}
object ExtensionsExample extends App{
import MyExtensions._
val t:Try[String] = Success("foo")
println(t.toEither)
val t2:Try[String] = Failure(new RuntimeException("bar"))
println(t2.toEither)
val e:Either[Throwable,String] = Right("foo")
println(e.toTry)
val e2:Either[Throwable,String] = Left(new RuntimeException("bar"))
println(e2.toTry)
}
【讨论】:
toTry 和 toEither 已包含在 scala 2.12 中。可能值得在您回答的顶部添加一个编辑。
import scala.util.{ Either, Failure, Left, Right, Success, Try }
implicit def eitherToTry[A <: Exception, B](either: Either[A, B]): Try[B] = {
either match {
case Right(obj) => Success(obj)
case Left(err) => Failure(err)
}
}
implicit def tryToEither[A](obj: Try[A]): Either[Throwable, A] = {
obj match {
case Success(something) => Right(something)
case Failure(err) => Left(err)
}
}
【讨论】:
Try 捕获它而不是用Failure 包装?
在 Scala 2.12.x 中 Try 有一个 toEither 方法:http://www.scala-lang.org/api/2.12.x/scala/util/Try.html#toEither:scala.util.Either[Throwable,T]
【讨论】:
答案取决于如何将Failure 转换为Left(反之亦然)。如果您不需要使用异常的详细信息,则可以通过Option 的中间路线将Try 转换为Either:
val tried = Try(1 / 0)
val either = tried.toOption.toRight("arithmetic error")
另一种方式的转换需要你构造一些 Throwable。可以这样做:
either.fold(left => Failure(new Exception(left)), right => Success(right))
【讨论】: