2011-11-11 39 views
10

我需要初始化一組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 ... 

但是,這涉及到複製的異常處理。

必須有一個「很好」的方式,但它躲過我。

+1

也許你利用延遲vals在下一次訪問時重新計算它們的值的事實,如果在初始化過程中引發異常? – soc

回答

5

一個簡單的解決方案是定義一個使用by-name參數的包裝函數。或者,如果您感覺真的很時髦,Scala 2.9允許使用部分函數作爲異常處理程序。

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

總的來說,我會說第一種方法是最直接的。但是如果你可以編寫可重複使用的異常處理程序,可以使用orElseandThen來組合,那麼第二種方法會更合適。

9

模式匹配怎麼樣?

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

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

你不需要'Some'。 –

+0

Thx,固定它... – agilesteel

+2

這是我希望允許多個答案被接受的情況之一。我已經接受戴夫的答案,因爲它最接近我最終使用的,但所有這些都是很好的方法。謝謝! –

7

agilesteel的回答是好的,如果你只是想趕上那真實拋出的任何異常,並做一些在catch塊程序。但是,您可能希望稍後單獨處理例外情況,在這種情況下,您可以考慮將類型設爲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) 

通知例外的變量賦值和處理現在怎麼是完全分開的。

+0

這是我希望允許多個答案被接受的情況之一。我已經接受戴夫的答案,因爲它最接近我最終使用的,但所有這些都是很好的方法。謝謝! –

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 } 
相關問題