Question

I want to flatten a Try[Option[T]] into a Try[T]

Here is my code

def flattenTry[T](t: Try[Option[T]]) : Try[T] = {
  t match {
    case f : Failure[T] => f.asInstanceOf[Failure[T]]
    case Success(e) => 
      e match {
        case None => Failure[T](new Exception("Parsing error"))
        case Some(s) => Success(s)
      }
  }
}

Is there a better way ?

Was it helpful?

Solution

You could try something like this which is a little neater:

val t = Try(Some(1))
val tt = t.flatMap{
  case Some(i) => Success(i) 
  case None => Failure(new Exception("parsing error"))
}

More generically, this would be:

def flattenTry[T](t: Try[Option[T]]) : Try[T] = {
  t.flatMap{
    case Some(s) => Success(s) 
    case None => Failure(new Exception("parsing error"))
  }    
}

The trick is to convert the Option into Try for using flatmap.

OTHER TIPS

Using getOrElse, you could also write:

def flattenTry[T](t: Try[Option[T]]): Try[T] = {
  t flatMap { o => o map (Success(_)) getOrElse Failure(new Exception("parsing error")) }
}

You could make this even shorter, but possibly at the cost of functional purity (throwing is a side-effect) and performance (due to throwing/catching):

def flattenTry[T](t: Try[Option[T]]): Try[T] = {
  Try(t.get getOrElse { throw new Exception("parsing error") })
}

One possible way is to use Try(o.get) to convert o: Option to o: Try.

This is very concise, but throws and catches exception when handling None, which might perhaps be a performance concern sometimes (or sometimes an ideological / code rules concern). Still, the code is so concise and well readable I think it is worth mentioning:

def flattenTry[T](t: Try[Option[T]]) : Try[T] = {
  t.flatMap(o => Try(o.get))
}

Note: not that I recommend using it, but for completeness: even a shorter version is possible, which throws / catches even when Try is a failure:

def flattenTry[T](t: Try[Option[T]]) : Try[T] = {
  Try(t.get.get)
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top