【发布时间】:2017-04-11 18:33:42
【问题描述】:
在线搜索答案给出了两个突出的帖子(Codacy's 和 Daniel Westheide's),并且都给出了与 Scala's official documentation for Try 相同的答案:
上面示例中显示的 Try 的一个重要属性是它能够管道或链接操作,沿途捕获异常。
上面引用的例子是:
import scala.io.StdIn
import scala.util.{Try, Success, Failure}
def divide: Try[Int] = {
val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)
val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt)
val problem = dividend.flatMap(x => divisor.map(y => x/y))
problem match {
case Success(v) =>
println("Result of " + dividend.get + "/"+ divisor.get +" is: " + v)
Success(v)
case Failure(e) =>
println("You must've divided by zero or entered something that's not an Int. Try again!")
println("Info from the exception: " + e.getMessage)
divide
}
}
但我可以使用传统的try 块轻松地进行流水线操作:
def divideConventional: Int = try {
val dividend = StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt
val divisor = StdIn.readLine("Enter an Int that you'd like to divide by:\n").toInt
val problem = dividend / divisor
println("Result of " + dividend + "/"+ divisor +" is: " + problem)
problem
} catch {
case (e: Throwable) =>
println("You must've divided by zero or entered something that's not an Int. Try again!")
println("Info from the exception: " + e.getMessage)
divideConventional
}
(注意:divide 和 divideConventional 在行为上略有不同,后者在出现问题的第一个迹象时会出错,但仅此而已。尝试输入“10a”作为dividend 的输入以查看我的内容意思。)
我想看看scala.util.Try 的流水线优势,但对我来说,这两种方法似乎是相等的。我错过了什么?
【问题讨论】:
-
注意
Try(...)只捕获非致命异常,所以它相当于`try { ... } catch { case NonFatal(e) => ... } -
请注意,
Try是类型系统的一部分。任何处理Try类型值的代码都“知道”它可能是其中一个。可能抛出的例程可以将其包装在Try中并将其作为其他人的问题传递。没有Try,就没有简单的沟通方式,“嘿!需要其他人来处理这个问题。” -
Daniel Westheide 在他的帖子中说:“如果您需要处理在其他线程上执行的 Actor 引发的异常,您显然无法通过捕获该异常来做到这一点。”我认为并发问题也很重要。
标签: scala try-catch monads codacy