为了理解尝试使用未处理的异常monad

时间:2017-10-15 08:36:09

标签: scala error-handling try-catch for-comprehension

我正在尝试学习如何在scala中使用Try with for comprehension。

在下面的示例代码中( result1 ),

如果for comprehension中的最后一个语句抛出一个未处理的异常, 代码不会中断并返回Try [Int]。

但是,如果为了理解而改变了语句序列( result2 )。抛出运行时异常。

package simpleTryExample

import scala.util.Try


object SimpleTryExample {

  def main(args: Array[String]): Unit = {

    val result1 = for {
      a <- strToInt("3")
      b <- strToInt("a")
    } yield (a + b)

    println("result1 is " + result1)

    val result2 = for {
      a <- strToInt("a")
      b <- strToInt("3")
    } yield (a + b)

    println("result2 is " + result2)

  }

  def strToInt(s: String): Try[Int] = {
    s match {
      case "a" =>
        println("input is a")
        throw new RuntimeException("a not allowed")
      case _ => println("other then a")
    }
    Try(s.toInt)
  }
}

输出: -

other then a
input is a
Exception in thread "main" java.lang.RuntimeException: a not allowed
    at simpleTryExample.SimpleTryExample$.strToInt(SimpleTryExample.scala:30)
    at simpleTryExample.SimpleTryExample$.main(SimpleTryExample.scala:18)
    at simpleTryExample.SimpleTryExample.main(SimpleTryExample.scala)
result1 is Failure(java.lang.RuntimeException: a not allowed)
input is a

我期待result2是Try [Int]类型。 我在这里做错了什么..?

1 个答案:

答案 0 :(得分:2)

问题在于,在第二个示例中,您在进入Try[T]上下文之前抛出了异常。

在您的第一个示例中,当您运行strToInt("a")时,您已经处于Try[T]的上下文中,因为代码被描述为:

strToInt("3").flatMap(_ => strToInt("a"))

由于strToInt的第一次调用成功,因此在for comprehension中执行的所有内容都在Try的上下文中。但是,在第二个例子中,我们却恰恰相反:

strToInt("a").flatMap(_ => strToInt("3"))

strToInt("a")会抛出RuntimeException,因为我们仍然不在<{1}}上下文中,它只会在您尝试解析{{1}时应用转到Try

要完全避免这种情况,请在模式匹配之前将尝试向上移动:

s

现在我们得到:

Int