我真的很喜欢Scala2.10中的scala.util.Try,它与for-comprehension一起工作的方式使得处理多个容易出错的步骤变得非常容易。
例如,我们可以使用下面的代码来确保当且仅当一切都在控制之下并且我们正确获取值时,才会打印出这两个数字。
def tryA: Try[Int] = {....}
def tryB: Try[Int] = {....}
for {
a <- tryA
b <- tryB
} {
println (s"We got:${a+b}")
}但我担心的是,这段代码实际上忽略了任何异常,这意味着它将看起来像下面的try-cactch块:
try {
// .....
} catch {
case _: Exception => // Swallow any exception
}据我所知,有一种说法认为这种代码是一种恶臭,因为没有人会注意到有异常发生。
我想要实现的是仍然使用for来确保println只在一切正常的情况下执行,但是如果在任何步骤中有任何异常,它将爆炸并直接抛出异常。
目前我是这样做的,但它似乎不那么优雅,因为它引入了一个新的Try[Unit]对象,所以我想知道如何才能使这段代码更好?
例如,有没有可能去掉result变量和result.get语句,但仍然抛出异常?
def tryA: Try[Int] = {....}
def tryB: Try[Int] = {....}
val result = for {
a <- tryA
b <- tryB
} yield {
println (s"We got:${a+b}")
}
result.get更新
更清楚地说,它是这个问题中第一个代码的Scala REPL的结果。
scala> def tryA: Try[Int] = Success(1)
tryA: scala.util.Try[Int]
scala> def tryB: Try[Int] = Failure(new Exception("error"))
tryB: scala.util.Try[Int]
scala> for {
| a <- tryA
| b <- tryB
| } {
| println (s"We got:${a+b}")
| }
scala> 我们可以看到这里什么都没有发生,即使是tryB也是一个异常的Failure。我希望得到的是一个抛出的异常,如果没有引入yield的新Try[Unit]对象,这是可能的吗?
发布于 2013-02-22 10:39:22
您可以使用recover
import scala.util.Try
def tryEven = Try { val i = (math.random * 1000).toInt; if (i % 2 != 0) throw new Exception("odd") else i }
def tryEvenOrNeg1 = Try { val i = (math.random * 1000).toInt; if (i % 2 != 0) throw new Exception("odd") else i } recover { case exx: Exception => -1 }
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
res1: scala.util.Try[Unit] = Failure(java.lang.Exception: odd)
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
res2: scala.util.Try[Unit] = Failure(java.lang.Exception: odd)
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
res3: scala.util.Try[Unit] = Failure(java.lang.Exception: odd)
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
Got 542, -1
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
res5: scala.util.Try[Unit] = Failure(java.lang.Exception: odd)
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
res6: scala.util.Try[Unit] = Failure(java.lang.Exception: odd)
scala> for (a <- tryEven; b <- tryEvenOrNeg1) yield println(s"Got $a, $b")
Got 692, 750我删除了反映Success(())的resNN。
发布于 2013-02-22 11:31:15
好吧,我忘了我们在Scala中总是有隐式转换。;-)
所以我们可以自己实现这个行为,它会比yield版本创建更多的对象,但我认为这段代码的意图要明确得多。
implicit class BlowUpTry[T](current: Try[T]) {
def throwIfFailed: Try[T] = current match {
case Success(value) => current
case Failure(exception) => throw exception
}
}
def tryA: Try[Int] = Success(1)
def tryB: Try[Int] = Failure(new Exception("error"))
for {
a <- tryA.throwIfFailed
b <- tryB.throwIfFailed
} {
println(s"We got ${a + b}")
}https://stackoverflow.com/questions/15015495
复制相似问题