【问题标题】:For comprehension Try monad with unhandled Exception为了理解尝试带有未处理异常的monad
【发布时间】:2017-10-15 08:36:08
【问题描述】:

我正在尝试学习如何在 scala 中使用 Try with 进行推导。

在下面的示例代码中(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] 类型。 我在这里做错了什么..?

【问题讨论】:

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


    【解决方案1】:

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

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

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

    由于strToInt 的第一次调用是成功的,在它之后在for 理解中执行的所有内容都在Try 的上下文中。但是,在第二个例子中,我们的情况正好相反:

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

    strToInt("a") 将抛出一个RuntimeException,因为我们仍然不是Try 上下文中,它仅在您尝试将s 解析为Int 时应用。

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

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

    现在我们得到:

    other then a
    input is a
    result1 is Failure(java.lang.RuntimeException: a not allowed)
    input is a
    result2 is Failure(java.lang.RuntimeException: a not allowed)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-11
      • 1970-01-01
      • 2011-11-23
      • 2018-06-02
      • 1970-01-01
      • 1970-01-01
      • 2015-02-08
      • 2021-01-01
      相关资源
      最近更新 更多