Is there a more elegant way of doing this in scala?
def doTheDangerousThing(): Try[Result] = { val result = Try(dangerousOp) if (result.isFailure) { println("error") } result } I think your if statement is perfectly valid. Here is another alternative:
def doTheDangerousThing(): Try[Result] = Try(dangerousOp) recoverWith { case exception => println("error"); Failure(exception) } recoverWith just for side-effecting, and not having to return Failure again.foreach method designed for Failure could be useful. You can write your own with implicit conversion.My preferred,
def doTheDangerousThing(): Option[Result] = Try (dangerousOp) toOption If the Try is successful you will get a Some(value), if it fails a None.
For a large compilation on Try uses, have a look at Try introduced in Scala 2.10.0 .
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 } toOption method in Try. And yes, it's not an answer.ExceptionThere 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 result all through, then:
def doTheDangerousThing(): Try[Result] = { Try(dangerousOp) recover { case ex => println("error"); throw ex } } foreach on that. It should ignore any Failure results, and work on any Success results, which seems to be exactly what I wanted (back 4 years ago, so please understand I have no recollection of this :)).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) I could choose from either of the three implementations, depending on whether I want to:
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
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)