在 try 块中保留最少的代码

Leaving minimal code inside try block

考虑这样定义的函数 f

def f() = {
  try { g(h()) }
  catch { case _: E => j() }
}

函数 ghj 实际上可以是任何 code/expression.

考虑到只有h可能会抛出E类型的异常,如何重写f使得在h中只剩下h try块?

如果 Scala try 块可以有一个 else 块 - 就像 Python 的一样 - f 的清晰定义可以这样写:

def f() =
  try { h() }
  catch { case _: E => j() }
  else { v => g(v) }  // v is the resulting value from the try block

不幸的是,Scala 不支持这样的事情。


这可能是一个——也许不是那么干净——可能的解决方案:

def f() = {
  val u =
    try { Some(h()) }
    catch { case _: E => None }

  u match {
    case Some(v) => g(v)
    case None => j()
  }
}

您可以改用 scala.util.Try。我在ideone测试的简单程序:

import scala.util.Try
object Main extends App {
    def f() = {
        Try(h()).map(g).recover { case _: Exception => j() }.get
    }

    def g(x: Any) = "g:" + x
    def h(): Any = throw new RuntimeException
    def j() = "caught"

    println(f())  // should print "g:caught"
}

老实说,我不会编写以 .get 结尾的代码(相反,如果我编写的代码可能引发异常,我会在整个代码库中传播 Try),但这应该是大致相当于你的例子。

Try { h() } match {
  case Sucess(x) => g(x) 
  case _ => j()
}
def f() = Try(h()).map(g).getOrElse(j()) 

map 你的 Try 结果。 g() 将仅在 Success() 上调用。使用 getOrElse()Failure() 上提供默认值。

import scala.util.Try

def h() = if (util.Random.nextBoolean) 7 else throw new Error
def g(x:Int) = x*5
def j() = 11

Try(h()).map(g).getOrElse(j())  // returns 35 or 11