I've recently seen code like this:
val maybeInt = catching(classOf[NFE]) opt arg.toInt
What is this opt
? An Option? Why isn't it using getOrElse to extract the value? In the above code, will maybeInt
be None if a NumberFormatException gets thrown?
catching
looks like it's some sort of method call, doesn't it? It is, but it actually returns an instance of a class Catch
; it doesn't directly take an argument. This class has two methods that are particularly useful for dealing with exceptions (and several more for catching multiple exceptions). The first is
def opt [U >: T] (body: ⇒ U) : Option[U]
which is being used here--you give it something that may throw an exception, and it will return Some(result)
if everything went okay, and None
if the targeted exception was caught:
scala> type NFE = NumberFormatException defined type alias NFE scala> import scala.util.control.Exception._ import scala.util.control.Exception._ scala> catching(classOf[NFE]).opt( "fish".toInt ) res0: Option[Int] = None scala> catching(classOf[NFE]).opt( "42".toInt ) res1: Option[Int] = Some(42)
You can then deal with this with map
or filter
or getOrElse
or whatever else you use to deal with options.
The other useful method is either
, which returns an instance of Left(exception)
if an exception was thrown, and a Right(result)
if it was not:
scala> catching(classOf[NFE]).either( "fish".toInt ) res2: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "fish") scala> catching(classOf[NFE]).either( "42".toInt ) res3: Either[Throwable,Int] = Right(42)
You can then use fold
or map to an option or whatever else you like doing with eithers.
Note that you can define a single catcher and use it multiple times (so you don't need to create the catcher object every time you, for example, parse an integer):
scala> val catcher = catching(classOf[NFE]) catcher: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException) scala> catcher.opt("42".toInt) res4: Option[Int] = Some(42) scala> catcher.opt("fish".toInt) res5: Option[Int] = None
Edit: as Daniel points out in the comments, this still creates a temporary Catch[Option]
; given the method signatures, there isn't an easy way to just have it trap exceptions and generate options without creating any extra objects. This reminds me why I write my own methods to do exactly that:
def optNFE[T](t: => T) = try { Some(t) } catch {case nfe: NFE => None} optNFE( "fish".toInt ) // gives None optNFE( "42".toInt ) // gives Some(42)
I use a more simple pattern when there is only one catch :
try{ return args.split(" ").exists(line.startsWith _) }catch { case _ =>{//generic exception logger.error("Error with line ${line} for ${ex.message}") throw _ } }
I'm definitely not yet a Scala pro, and I guess you could find shorter stuff
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With