Dan*_* Li 7 monads scala try-catch codacy
在线搜索答案给出了两个突出的帖子(Codacy和Daniel Westheide),两者都给出了与Scala官方文档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
}
}
Run Code Online (Sandbox Code Playgroud)
但我可以使用传统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
}
Run Code Online (Sandbox Code Playgroud)
(注意:divide并且divideConventional行为略有不同,因为后者在出现问题的第一个迹象时出错,但就是这样.尝试输入"10a"作为输入dividend来看看我的意思.)
我试图看到scala.util.Try流水线的优势,但对我来说似乎两种方法是平等的.我错过了什么?
我认为你很难看到组合能力,Try[T]因为你在两种情况下都在本地处理异常.如果您想要进行divideConventional额外的操作,该怎么办?
我们有一些喜欢:
def weNeedAnInt(i: Int) = i + 42
Run Code Online (Sandbox Code Playgroud)
然后我们会有类似的东西:
weNeedAnInt(divideConventional())
Run Code Online (Sandbox Code Playgroud)
但是,假设您想要最大化允许用户输入的重试次数(这通常是您在现实生活中的情况,您无法永远重新输入方法?我们必须另外包装通过以下方式调用weNeedAnInt自身try-catch:
try {
weNeedAnInt(divideConventional())
} catch {
case NonFatal(e) => // Handle?
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我们使用divide,并且假设它没有在本地处理异常并向外传播内部异常:
def yetMoreIntsNeeded(i: Int) = i + 64
val result = divide.map(weNeedAnInt).map(yetMoreIntsNeeded) match {
case Failure(e) => -1
case Success(myInt) => myInt
}
println(s"Final output was: $result")
Run Code Online (Sandbox Code Playgroud)
这不简单吗?也许,我认为这有一些主观性的答案,我发现它更清洁.想象一下,我们有一个很长的这样的操作流程,我们可以将每个操作组合Try[T]到下一个,并且只有在管道完成后才会担心问题.