在try块中留下最少的代码

时间:2016-10-29 00:39:50

标签: scala syntax code-cleanup code-structure

考虑以这种方式定义的函数f

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

函数ghj实际上可以是任何代码/表达式。

考虑到只有h可能会抛出E类型的异常,如何重写f,以便只有h留在try内阻止?

4 个答案:

答案 0 :(得分:3)

Try { h() } match {
  case Sucess(x) => g(x) 
  case _ => j()
}

答案 1 :(得分:2)

您可以使用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,如果我正在编写可以抛出异常的代码),但这应该大致相当于举个例子。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

如果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()
  }
}