初始化可能引发异常的val

时间:2011-11-11 23:08:02

标签: scala

我需要初始化一组val,其中初始化它们的代码可能会引发异常。我很乐意写:

try {
  val x = ... generate x value ...
  val y = ... generate y value ...
} catch { ... exception handling ... }

... use x and y ...

但是这(显然)不起作用,因为x和y不在try的范围之外。

使用可变变量很容易解决问题:

var x: Whatever = _
var y: Whatever = _
try {
  x = ... generate x value ...
  y = ... generate y value ...
} catch { ... exception handling ... }

... use x and y ...

但那不是很好。

通过复制异常处理也很容易解决问题:

val x = try { ... generate x value ... } catch { ... exception handling ... }
val y = try { ... generate y value ... } catch { ... exception handling ... }

... use x and y ...

但这涉及重复异常处理。

必须有一种“好”的方式,但这是我的意思。

4 个答案:

答案 0 :(得分:9)

模式匹配怎么样?

val (x, y) = try generateX -> generateY catch { /*exception handling*/ }

val (x, y) = try (generateX, generateY) catch { /*exception handling*/ }

答案 1 :(得分:7)

如果你只想抓住抛出的任何异常并在catch块中执行某些程序,那么agilesteel的答案就可以了。但是,您可能希望稍后单独处理异常,在这种情况下,您可以考虑将类型设为OptionEither

执行此操作的内置方法是使用Catch对象。请参阅Exception docs

如何使用它取决于发生异常时您想要发生的事情。例如

import util.control.Exception.allCatch

def handleInfinities(n: Int) = {
  val x = allCatch.either { 100 / n }        // Either[Throwable, Int]
  val y = allCatch.either { 100 / (n - 1) }

  Seq(x, y) map { case Left(_) => Int.MaxValue; case Right(z) => z }
}

然后handleInfinities(1)给出了

Seq[Int] = List(100, 2147483647)

注意变量赋值和异常处理现在是如何完全分开的。

答案 2 :(得分:5)

一个简单的解决方案是定义一个使用by-name参数的包装函数。

def safely[T](f: => T): T = try { f } catch { /* exception handling */ }
// You'll have to play around with safely's type signature, depending on what
// you do in the exception handling
val x = safely { generateX }
val y = safely { generateY }

或者,如果你感觉真的很时髦,Scala 2.9允许将部分函数用作异常处理程序。

val handler: PartialFunction[Throwable, Unit] = { /* exception handling */ }
val x = try { generateX } catch handler
val y = try { generateY } catch handler

总的来说,我会说第一种方法最直接。但是,如果您可以编写可重用的异常处理程序,可以使用orElseandThen组合在一起,那么第二种方法会更合适。

答案 3 :(得分:1)

import util.control.Exception._
def handler[A]: Catch[A] = handling(classOf[Exception]) by exceptionHandlingFunc
val x = handler[X] apply { generateX }
val y = handler[Y] apply { generateY }