在scala中有更优雅的方法吗?
def doTheDangerousThing(): Try[Result] = {
val result = Try(dangerousOp)
if (result.isFailure) {
println("error")
}
result
}
答案 0 :(得分:13)
我认为你的if语句完全有效。这是另一种选择:
def doTheDangerousThing(): Try[Result] = Try(dangerousOp) recoverWith {
case exception => println("error"); Failure(exception)
}
答案 1 :(得分:4)
这样的事情:
def doTheDangerousThing[Result](dangerousOp: =>Result): Try[Result] = Try(dangerousOp) match {
case o @ Failure(_) => println("error"); o
case _ => _
}
答案 2 :(得分:4)
不确定这是否更具惯用性,但有时我发现以这种方式放置recoverWith
会提高我的可读性:
def doDangerousThing(): Try[Result] = Try {
dangerousOp
} recoverWith {
case t: Throwable => println("error"); Failure(t)
}
答案 3 :(得分:2)
我的首选,
def doTheDangerousThing(): Option[Result] = Try (dangerousOp) toOption
如果Try
成功,如果Some(value)
失败,您将获得None
。
有关Try
次使用的大型编辑,请查看Try introduced in Scala 2.10.0。
答案 4 :(得分:2)
有办法。例如:
def doTheDangerousThing(): Try[Result] = {
val result = Try(dangerousOp)
result.failed foreach { _ =>
println("error")
}
result
}
或者,如果您不想重复result
,那么:
def doTheDangerousThing(): Try[Result] = {
Try(dangerousOp) recover {
case ex => println("error"); throw ex
}
}
答案 5 :(得分:1)
在某些情况下,我喜欢使用两步法,这将允许我更细粒度的错误信息控制:
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)
答案 6 :(得分:0)
好吧,我想你可以这样做:
def doTheDangerousThing(): Option[Result] =
Try(dangerousOp) match {
case Success(result) => Some(result)
case Failure(e) => None //might want to log the error as well
}
答案 7 :(得分:0)
我可以从三种实现中选择一种,具体取决于我是否:
doTheDangerousThing1
)doTheDangerousThing2
)doTheDangerousThing3
)以下是代码:
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
}
}
}
在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)
答案 8 :(得分:0)
添加像foreach这样的方法但是像@vptheron这样的失败的隐式类会看起来像这样
implicit class EnhancedTry[T](t: Try[T]) {
def forfailed[U](f: Throwable => U): Unit = t match {
case Failure(e) => f(e)
case _ => ()
}
}
然后我们可以做
val t = Try {
throw new Exception("An error")
}
t.forfailed(e => println(e.getMessage))
// or use pattern matching
t.forfailed {
case e : NullPointerException => println("NPE " + e.getMessage)
case e => println("Other " + e.getMessage)
}
f: Throwable => U
的类型也可以是Throwable => Unit
,但我已经模仿foreach
上函数参数的返回类型。
我无法弄清楚为什么它有一个泛型返回类型而不是Unit。