与scala.util.Try配合使用时快速失败 [英] Quick failure when using for-comprehension with scala.util.Try

查看:153
本文介绍了与scala.util.Try配合使用时快速失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的很喜欢Scala 2.10中的 scala.util.Try ,它如何与理解一起使用,可以处理容易出错的多个步骤。

I really like scala.util.Try in Scala 2.10, and how it works with for-comprehension makes handling multiple steps that could go wrong easily.

例如,我们可以使用以下代码来确保仅当所有情况都在控制之下并且我们正确获得价值时,才打印出两个数字。

For example, we could use the following code to make sure we only print out that two numbers if and only if everything is under control and we get value correctly.

def tryA: Try[Int] = {....}
def tryB: Try[Int] = {....}

for {
  a <- tryA
  b <- tryB
} { 
  println (s"We got:${a+b}")
}

但我担心的是该代码实际上忽略了任何异常,这意味着它看起来像下面的try-cactch块:

But one of my concern is that this code is actually ignore any exceptions, which means it will looks like the following try-cactch block:

try {
  // .....
} catch {
  case _: Exception => // Swallow any exception
}

据我所知,有一个论点是这种代码是难闻的气味,因为没有人会注意到有异常发生。

As far as I know, there is an argument that this kind of codes is a bad smell, because no one will notice there is an exception occurs.

我想实现的是仍然使用 for 来确保 println 仅在一切正常的情况下执行,但如果任何步骤中有任何异常,它将炸毁并直接抛出该异常。

What I would like to achieve is that still using for to make sure the println only execute if everything is OK, but if there is any exception in any steps, it will blow up and throw out the exception directly.

目前,这是我的操作方式,但由于它引入了新的 Try [Unit] 对象,因此看起来不太优雅,所以我想知道如何才能使此代码更好?

Currently here is how I do this, but it seems less elegant because it introduce a new Try[Unit] object, so I'm wondering how could I make this code better?

例如,是否可以摆脱 result 变量和 result。 get 语句,但仍然会引发异常?

For example, is it possible to get rid of the result variable and result.get statement, but still get exception being thrown?

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的结果

Update

To make thing more clear, it is the result from Scala REPL of the first code in this question.

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 失败,但有例外。我想得到的是抛出一个异常,并且没有引入新的 Try [Unit] 对象,其收益为 ,这可能吗?

We can see that nothing happens here, even tryB is a Failure with exception. What I would like to get is an exception being thrown, and without the introduce the new Try[Unit] object with yield, is this possible?

推荐答案

您可以使用恢复

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 >。

I removed the resNN that reflected Success(()).

这篇关于与scala.util.Try配合使用时快速失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆