Catching an exception within a map

shj picture shj · Nov 3, 2010 · Viewed 12.3k times · Source

What is the best way of handling exceptions while iterating over a loop in Scala?

For instance, if I had a convert() method that could throw an exception, I'd like to catch that exception, log it, and keep iterating. Is there a "scala" way to do this?

Ideally, I'd like something like...

val points: Seq[Point] = ...
val convertedPoints: Seq[ConvertedPoint] = points.map(
   p => {
     try { p.convert() } 
     catch { case ex: Exception => logger.error("Could not convert", ex) }
})

You can't do the above code since it's not a direct mapping from one list to the other (you get back Seq[Any] as opposed to Seq[ConvertedPoint]).

Answer

Daniel C. Sobral picture Daniel C. Sobral · Nov 4, 2010

Interesting that I had a lot of trouble explaining the advantages of using scala.util.control.Exception over try/catch, and then I start to see questions that make perfect examples out of them.

Here:

import scala.util.control.Exception._
List(1, 23, 5, 2, 0, 3, 2) flatMap (x => catching(classOf[Exception]) opt (10 / x))

Your own code would look like this:

val points: Seq[Point] = ...
val convertedPoints: Seq[ConvertedPoint] = points.flatMap(
  p => handling(classOf[Exception]) by { ex =>
    logger.error("Could not convert", ex); None
  } apply Some(p.convert)
)

Or, if you refactor it:

val exceptionLogger = handling(classOf[Exception]) by { ex =>
    logger.error("Could not convert", ex); None
}
val convertedPoints: Seq[ConvertedPoint] = points.flatMap(p => exceptionLogger(Some(p.convert)))