Reputation: 42050
Suppose I have a function f: Int => String
which may throw exceptions. I would like to write a function tryF(f: Int => String, arg: Int, defaultOpt: Option[String])
, which works as follows:
f(arg)
and return the result if it has thrown no exceptiondefaultOpt.isDefined
then return defaultOpt.get
I am writing it as follows:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
r.toOption orElse defaultOpt getOrElse r.get
}
Does it make sense ? Would you rewrite it ?
Upvotes: 0
Views: 199
Reputation: 9134
No need for Try
in your case; try
/catch
is enough:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
try {
f(arg)
} catch {
case e: Exception => defaultOpt getOrElse { throw e }
}
}
If you want to use Try
, I'd suggest taking advantage of recover
:
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
Try {
f(arg)
}.recover({
case _ if defaultOpt.isDefined => defaultOpt.get
}).get
}
However, if this is your actual function, I'd consider rewriting the argument types to be generic, rather than rewriting the implementation, as long as the implementation already works:
def tryF[A, B](f: A => B, arg: A, defaultOpt: Option[B]): B = /* ... */
Upvotes: 2
Reputation: 12563
A verbose, but easy-to-understand way...
import scala.util.{Try,Success,Falure}
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
Try(f(arg)) match {
case Success(r) => r
case Failure(ex) => defaultOpt match {
case Some(content) => content
case None => throw ex
}
}
Slightly more compact way:
import scala.util.{Try,Success,Falure}
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) =
Try(f(arg)) match {
case Success(r) => r
case Failure(ex) => defaultOpt getOrElse {throw ex}
}
Upvotes: 2
Reputation: 8851
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
if (r.isSuccess) r.get else defaultOpt.getOrElse(r.get)
// reads like -> if r is success, get from r, else get from default, else get from r
}
Upvotes: 1
Reputation: 1830
def tryF(f: Int => String, arg: Int, defaultOpt: Option[String]) = {
val r = scala.util.Try(f(arg))
(r, defaultOpt) match {
case (Success(result), _) => result
case (Failure(_), Some(opt)) => opt
case (Failure(ex), None) => throw ex
}
Upvotes: 1
Reputation: 7466
Your solution is fine even though I personally don't find it very readable. I would do something like that:
def tryF[A](f: =>A, defaultOpt: Option[A]): A = (Try(f), defaultOpt) match {
case (Success(result), _) => result
case (Failure(_), Some(defValue)) => defValue
case (Failure(t), None) => throw t
}
Note that it is unnecessarily verbose (I could have used wildcard in some of the cases) but I think your use case deserves some self documenting code. It is easy to understand what triggers each case.
Upvotes: 5