为了理解尝试使用未处理异常的 monad
For comprehension Try monad with unhandled Exception
我正在尝试学习如何在 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] 类型。
我在这里做错了什么..?
问题在于,在您的第二个示例中,您在进入 Try[T]
上下文之前抛出了异常。
在您的第一个示例中,当 运行 strToInt("a")
时,您已经处于 Try[T]
的上下文中,因为代码被压缩为:
strToInt("3").flatMap(_ => strToInt("a"))
由于 strToInt
的第一次调用是成功的,因此在 for comprehension 中它之后执行的所有内容都在 Try
的上下文中。但是,在第二个例子中,我们有相反的情况:
strToInt("a").flatMap(_ => strToInt("3"))
strToInt("a")
将抛出一个 RuntimeException
因为我们 仍然没有 在 Try
上下文中,它仅在您尝试时应用将 s
解析为 Int
.
为了完全避免这种情况,请在模式匹配之前将尝试移到更高的位置:
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)
我正在尝试学习如何在 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] 类型。 我在这里做错了什么..?
问题在于,在您的第二个示例中,您在进入 Try[T]
上下文之前抛出了异常。
在您的第一个示例中,当 运行 strToInt("a")
时,您已经处于 Try[T]
的上下文中,因为代码被压缩为:
strToInt("3").flatMap(_ => strToInt("a"))
由于 strToInt
的第一次调用是成功的,因此在 for comprehension 中它之后执行的所有内容都在 Try
的上下文中。但是,在第二个例子中,我们有相反的情况:
strToInt("a").flatMap(_ => strToInt("3"))
strToInt("a")
将抛出一个 RuntimeException
因为我们 仍然没有 在 Try
上下文中,它仅在您尝试时应用将 s
解析为 Int
.
为了完全避免这种情况,请在模式匹配之前将尝试移到更高的位置:
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)