使用-理解与scala.util.Try时快速故障(Quick failure when using

2019-08-17 02:56发布

我真的很喜欢scala.util.Try在斯卡拉2.10,和它是如何工作与-理解使得处理多个步骤可能出错容易。

例如,我们可以使用下面的代码,使当且仅当一切都在控制之下,我们正确地得到价值肯定我们只打印出两个数字。

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

更新

为了让事情更清晰,它是在这个问题上的第一个代码的斯卡拉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 ,出现异常。 我想获得是抛出一个异常,并没有引入新的Try[Unit]与目标yield ,这可能吗?

Answer 1:

你可以使用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

我删除了resNN反映Success(())



Answer 2:

OK,我忘了,我们总是在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}")
}


文章来源: Quick failure when using for-comprehension with scala.util.Try