View Natalino Busa's profile on LinkedIn

Principal Data Scientist, Director for Data Science, AI, Big Data Technologies. O’Reilly author on distributed computing and machine learning.​

Natalino leads the definition, design and implementation of data-driven financial and telecom applications. He has previously served as Enterprise Data Architect at ING in the Netherlands, focusing on fraud prevention/detection, SoC, cybersecurity, customer experience, and core banking processes.

​Prior to that, he had worked as senior researcher at Philips Research Laboratories in the Netherlands, on the topics of system-on-a-chip architectures, distributed computing and compilers. All-round Technology Manager, Product Developer, and Innovator with 15+ years track record in research, development and management of distributed architectures, scalable services and data-driven applications.

Sunday, July 15, 2012

Monadic exceptions in Scala

When discussing monads in Scala the first examples are of related to the Option and the Either types.

When you go a bit deeper into the meaning of monads and functional programming, you soon realize that functional programming in scala, essentially means that any List, Seq, Array, Map are actually all monads. Monads can be composed via binding (in scala this is done via map and flatMat), and can be chained via a series of flatMap to produce your final result.

But what about exceptions?
If you are not a theoretician, you will soon realize that exceptions do happen in scala, especially if you use vanilla programming via a mixture of Java and Scala libraries.

Scala comes to the rescue with an object which can transform any function which could potentially throw an exception into a monad. This is quite a big thing since by using this scala class you can render all you existing java and scala code completely side effect free. This means that you can encapsulate any code in a full functional programming paradigm.

The class is called Catch and it doesn't directly take an argument, but it defines a closure around your own code.
This class has two methods that are particularly useful for dealing with exceptions (and several more for catching multiple exceptions).

These are the opt and either methods:

def opt [U >: T] (body: ⇒ U) : Option[U]
def either[U >: T](body: ⇒ U): Either[Throwable, U]

The library provides a handful of method which can construct a Catch object for you.
Two of those are catching and allCatch

If you use the opt method it will return Some(result) if everything went okay, and None if the targeted exception was caught:

scala> import scala.util.control.Exception._
import scala.util.control.Exception._

scala> catching(classOf[NumberFormatException]).opt( "apples".toInt )
res0: Option[Int] = None

scala> catching(classOf[NumberFormatException]).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.
Either returns an instance of Left(exception) if an exception was thrown, and a Right(result) if it was not:

scala> catching(classOf[NumberFormatException]).either( "fish".toInt )
res2: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "fish")

scala> catching(classOf[NumberFormatException]).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 either.
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[NumberFormatException])
catcher: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)

scala> catcher.opt("42".toInt)
res4: Option[Int] = Some(42)

scala> catcher.opt("apples".toInt)
res5: Option[Int] = None

If you want to catch everything, you can also use the handy allCatch method

scala> allCatch.opt( "42".toInt )
res2: Option[Int] = Some(42)

scala> allCatch.either( "apples".substring(8, 4) )
res11: Either[Throwable,java.lang.String] =
Left(java.lang.StringIndexOutOfBoundsException: String index out of range: -4)

scala> allCatch.either( "apples".toInt )
res5: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "apples")

Popular Posts

Featured Post

The AI scene in the valley: A trip report

A few weeks back I was lucky enough to attend and present at the Global AI Summit in the bay area. This is my personal trip report about th...