scala:如何避免try catch块中的mutables

时间:2012-09-11 04:57:17

标签: scala exception exception-handling immutability

我正在尝试避免mutables变量,但问题是我必须访问我需要在try内部初始化的val(这是一个迁移失败的db操作),我需要在finally块中使用var < / p>

我尝试了几种方法:

在try块中声明val

try {
  val resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

error: not found: value resultSet

在try块之外声明val而不初始化

val resultSet: java.sql.ResultSet
try {
  resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

error: only classes can have declared but undefined members

使用var,这似乎有用

var resultSet: java.sql.ResultSet = null
try {
  resultSet = SQL(sql).resultSet
  return ColumnInfo(resultSet.getMetaData)
} catch {
  case e => throw new ColumnInfoException("Error getting metadata")
} finally {
  resultSet.close
}

最后嵌套try-catch块,看起来很脏

try {
  val resultSet = SQL(sql).resultSet
  try {
    return ColumnInfo(resultSet.getMetaData)
  } catch {
    case e => throw new ColumnInfoException("Error getting metadata")
  } finally {
    resultSet.close
  }
} catch {
  case e => throw new ColumnInfoException("Error opening resultSet")
}

我可以采取一些更好的方法来避免使用变量和嵌套try-catch块吗?

4 个答案:

答案 0 :(得分:3)

import scala.util.control.Exception._

allCatch.either(SQL(sql).resultSet).right.flatMap{ resultSet =>
  val ans = allCatch.either(ColumnInfo(resultSet.getMetaData))
  resultSet.close
  ans
}.fold(e => throw e, identity)

或者您可以跳过fold并将例外文件打包在Left中。

答案 1 :(得分:2)

来自这个问题functional try & catch w/ Scala

我了解了贷款模式:https://wiki.scala-lang.org/display/SYGN/Loan

Play框架本身似乎与DB.withConnection方法一起使用

答案 2 :(得分:1)

在Scala中,try阻止为an expression。在您的情况下,它可以评估为包含val s:

的元组
val res: (java.sql.ResultSet, ColumnInfo) = try {
  val rs = SQL(sql).resultSet
  (rs, ColumnInfo(rs.getMetaData))
} catch {
  case _: Throwable => throw new Exception("Error getting metadata")
} finally {
  res._1.close
}
val columnInfo = res._2

答案 3 :(得分:0)

摆脱第一个障碍:

try {
  val resultSet = SQL(sql).resultSet
  try {
    ColumnInfo(resultSet.getMetaData)
  } finally {
    resultSet.close
  }
} catch {
  case e => throw new ColumnInfoException("Error opening resultSet")
}