简体   繁体   中英

Scala Try and Either Weird Behavior

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:

  1. throw f wouldn't compile: "Expression of type Serializable doesn't conform to expected type Throwable". Thus the cast.
  2. Exception from sample run 2:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM