初始化可能引发异常的val

Pau*_*her 10 scala

我需要初始化一组val,初始化它们的代码可能会引发异常.我想写:

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

... use x and y ...
Run Code Online (Sandbox Code Playgroud)

但是这(显然)不起作用,因为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 ...
Run Code Online (Sandbox Code Playgroud)

但那并不是很好.

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

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

... use x and y ...
Run Code Online (Sandbox Code Playgroud)

但这涉及重复异常处理.

必须有一个"好"的方式,但它是在逃避我.

agi*_*eel 9

模式匹配怎么样?

val (x, y) = try generateX -> generateY catch { /*exception handling*/ }
Run Code Online (Sandbox Code Playgroud)

要么

val (x, y) = try (generateX, generateY) catch { /*exception handling*/ }
Run Code Online (Sandbox Code Playgroud)

  • 这是我希望允许多个答案被接受的情况之一.我接受了戴夫的答案,因为它最接近我最终使用的答案,但所有这些都是很好的方法.谢谢! (2认同)

Lui*_*hys 7

agilesteel的答案很好,如果你只想捕获任何抛出的异常并在catch块中执行某些程序.但是,您可能希望稍后单独处理异常,在这种情况下,您可能会考虑将类型设置为OptionEither.

执行此操作的内置方法是使用Catch对象.请参阅例外文档.

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

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 }
}
Run Code Online (Sandbox Code Playgroud)

然后handleInfinities(1)给出

Seq[Int] = List(100, 2147483647)
Run Code Online (Sandbox Code Playgroud)

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


lee*_*777 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 }
Run Code Online (Sandbox Code Playgroud)

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

val handler: PartialFunction[Throwable, Unit] = { /* exception handling */ }
val x = try { generateX } catch handler
val y = try { generateY } catch handler
Run Code Online (Sandbox Code Playgroud)

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