So I am playing with the M
types in Scala and came up with the following regarding Try
and Either
:
def brokers(throw1: () => List[Int], throw2: List[Int] => List[String]) = {
println("brokers ===> " +
(Try(throw1())
.toEither
.filterOrElse(!_.isEmpty, Nil)
.flatMap(xs => Try(throw2(xs)).toEither) match {
case Right(s) => s
case Left(f) => throw f.asInstanceOf[Throwable]
})
)
}
And some test runs:
brokers(() => List(1, 2, 3), (xs: List[Int]) => xs.map(_.toString))
brokers(() => Nil, (xs: List[Int]) => throw new RuntimeException("throw2"))
brokers(() => Nil, (xs: List[Int]) => xs.map(_.toString))
brokers(() => throw new RuntimeException("throw1"), (xs: List[Int]) => xs.map(_.toString))
brokers(() => List(1, 2, 3), (xs: List[Int]) => throw new RuntimeException("throw2"))
But:
throw f
wouldn't compile: "Expression of type Serializable doesn't conform to expected type Throwable". Thus the cast. Exception in thread "main" java.lang.ClassCastException: scala.collection.immutable.Nil$ cannot be cast to java.lang.Throwable at Practice$.brokers(Practice.scala:57) at Practice$.delayedEndpoint$Practice$1(Practice.scala:63)
Why, Scala, why?
Answering my own question, turns out Either.filterOrElse
is not really what I thought it to be. If the predicate doesn't match, filterOrElse
actually converts Either[A, B]
to Either[AA, B]
where AA
is the "zero" element provided to filterOrElse
. In my case, it converted the Either[Throwable,List[Int]] = Right(List())
to a Either[java.io.Serializable,List[Int]] = Left(List())
. Thus the compile error, and the match with case Left
and eventual exception. The Serializable
must have come from the contravariant type parameter AA >: A
, because guess what, the first common supertype for Throwable
and List
is a Serializable
.
I've filed SI-10044 for this; will see what they say.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.