scala 的 Try 优雅的错误行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21556310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:02:46  来源:igfitidea点击:

scala's Try elegant on error behavior

scalarefactoringtry-catch

提问by Pablo Fernandez

Is there a more elegant way of doing this in scala?

在 Scala 中是否有更优雅的方式来做到这一点?

def doTheDangerousThing(): Try[Result] = {
  val result = Try(dangerousOp)

  if (result.isFailure) {
     println("error")
  }

  result
}

回答by vptheron

I think your if statement is perfectly valid. Here is another alternative:

我认为你的 if 语句是完全有效的。这是另一种选择:

def doTheDangerousThing(): Try[Result] = Try(dangerousOp) recoverWith {
    case exception => println("error"); Failure(exception)
}

回答by Alex

Not sure if this is more idiomatic, but sometimes I find that placing the recoverWithin this manner improves readability for me:

不确定这是否更惯用,但有时我发现recoverWith以这种方式放置可以提高我的可读性:

def doDangerousThing(): Try[Result] = Try {
  dangerousOp
} recoverWith {
  case t: Throwable => println("error"); Failure(t)
}

回答by Sane

Something like this:

像这样的东西:

   def doTheDangerousThing[Result](dangerousOp: =>Result): Try[Result] = Try(dangerousOp) match {
    case o @ Failure(_) =>  println("error"); o
    case _ => _
  }

回答by elm

My preferred,

我的首选,

def doTheDangerousThing(): Option[Result] = Try (dangerousOp) toOption

If the Tryis successful you will get a Some(value), if it fails a None.

如果Try成功,您将获得一个Some(value),如果失败则获得一个None

For a large compilation on Tryuses, have a look at Try introduced in Scala 2.10.0.

有关使用的大型编译Try查看Scala 2.10.0 中引入的 Try

回答by Daniel C. Sobral

There are ways. For instance:

有办法。例如:

def doTheDangerousThing(): Try[Result] = {
  val result = Try(dangerousOp)

  result.failed foreach { _ =>
     println("error")
  }

  result
}

Or, if you don't want to repeat resultall through, then:

或者,如果您不想一直重复result,则:

def doTheDangerousThing(): Try[Result] = {
  Try(dangerousOp) recover {
    case ex => println("error"); throw ex
  }
}

回答by Johnny

In some cases I love to use two-step approach which will allow me a more granular error message control:

在某些情况下,我喜欢使用两步法,这将允许我进行更细粒度的错误消息控制:

  def retrieveData(dataId: String): Try[String] = {
    Try {
      Option(someApi(dataId))
        .getOrElse(throw SomeApiFailedException("invalid dataId"))
    } recoverWith {
      case e: SomeApiFailedException => Failure(e)
      case e: Throwable => Failure(SomeApiFailedException("failed retrieve dataId"))
    }
  }

  case class SomeApiFailedException(err: String) extends RuntimeException(err)

回答by tuxdna

I could choose from either of the three implementations, depending on whether I want to:

我可以从三个实现中的任何一个中进行选择,具体取决于我是否想要:

  • Simply propagate it upwards ( doTheDangerousThing1)
  • Ignore the error ( doTheDangerousThing2)
  • Intercept the error while propagating it upwards ( doTheDangerousThing3)
  • 只需向上传播 ( doTheDangerousThing1)
  • 忽略错误 ( doTheDangerousThing2)
  • 向上传播时截获误差 ( doTheDangerousThing3)

Here is the code:

这是代码:

import scala.util.{Try,Success,Failure}
object temp {
  type Result = Int

  def dangerousOp = {
    val r = scala.util.Random.nextInt(10)
    if (r > 5) r else throw new RuntimeException("Failed on " + r)
  }
  def logMessage[T](t: T) = println(t)

  def doTheDangerousThing1(): Try[Result] = Try(dangerousOp)

  def doTheDangerousThing2(): Option[Result] = {
    Try(dangerousOp) match {
      case Success(r) => Option(r)
      case _ => None
    }
  }


  def doTheDangerousThing3(): Try[Result] = {
    Try(dangerousOp) match {
      case t @ Success(r) => t
      case t @ _ => logMessage("failed: "+t); t
    }
  }
}

Inside the REPL

REPL 内部

scala> doTheDangerousThing1
res0: scala.util.Try[Result] = Success(9)

scala> doTheDangerousThing1
res1: scala.util.Try[Result] = Success(9)

scala> doTheDangerousThing2
res2: Option[Result] = None

scala> doTheDangerousThing2
res3: Option[Result] = Some(7)

scala> doTheDangerousThing3
failed: Failure(java.lang.RuntimeException: Failed on 0)
res4: scala.util.Try[Result] = Failure(java.lang.RuntimeException: Failed on 0)

scala> doTheDangerousThing3
failed: Failure(java.lang.RuntimeException: Failed on 0)
res5: scala.util.Try[Result] = Failure(java.lang.RuntimeException: Failed on 0)

回答by James Adam

Well, I suppose you could do something like this:

好吧,我想你可以这样做:

def doTheDangerousThing(): Option[Result] = 
  Try(dangerousOp) match {
    case Success(result) => Some(result)
    case Failure(e) => None //might want to log the error as well
  }