Options and Exceptions in Scala

Option is solution to a Billion Dollar Mistake introduced by Null Pointer Exceptions. Options deal with unsafe APIs and never do null checks.
As .get is a unsafe operation, we should rely on map/flatMap to read the values from options.
Since we can use map, flatMap on options, we can also use for comprehension.

Scala Implementation Classes

        sealed abstract class Option[+A]
        case class Some[+A](x: A) extends Option[A]
        case object None extends Option[Nothing]

Code Sample

     val config: Map[String, String] = Map(
             "age" -> "36",
             "gender" -> "Male"
         )

         class Person {
             def getPerson = println("person created")
         }
         object Person {
             val random = new Random(System.nanoTime())

             def apply(age: String, gender: String): Option[Person] =
                 if(random.nextBoolean()) Some(new Person)
                 else None
         }

         // by default .get on map returns option
         val age = config.get("age")
         val gender = config.get("gender")
         // NOTE: age.get is unsafe operation and hence we should only rely on map/flatMap to get the value from options
         /*
             if (age != null && gender != null)
                 return Person(age, gender)
             else
                 return null
          */
         val person = age.flatMap(a => gender.flatMap(g => Person(a, g)))
         /*
             if (person != null)
                 return person.getPerson
             else
                 return null
          */
         val personStatus = person.map(c => c.getPerson)
         /*
             Same as
             if (status != null)
                 println(status)
          */
         personStatus.foreach(println)

         // shorthand chained solution
         config.get("age")
           .flatMap(h => config.get("gender")
             .flatMap(p => Person(h, p))
             .map(c => c.connect))
           .foreach(println)

         // for comprehensions: Instead of using chained or multiple map/flatmaps we can use this for readability (much widely used and more readable)
         // If any of the the for statements in None, then entire for-yield will return None
         val forPersonStatus = for {
             age <- config.get("age")
             gender <- config.get("gender")
             Person <- Person(age, gender)
         } yield Person.connect

         forPersonStatus.foreach(println)

Exceptions
In imperative languages like Java, as number of try blocks increases, program becomes barely readable
Scala provides a way to avoid countless try-catch blocks

Scala Implementation Classes

        sealed abstract class Try[+T]
        case class Failure[+T](t: Throwable) extends Try[T]
        case class Success[+T](value: T) extends Try[T]

Code Sample

     val aSuccess = Success(3)
         val aFailure = Failure(new RuntimeException("Not valid"))
         println(aSuccess)
         println(aFailure)

         // unsafe methods
         def unsafeMethod = throw new RuntimeException("Unsafe method invoked")
         // Try with apply method is going to catch the exception and wrap it in Failure object
         val potentialFailure = Try(unsafeMethod)
         println(potentialFailure)
         println(potentialFailure.isSuccess) // tells whether exception is thrown or not

         // orElse
         def backUpMethod(): String = "A valid result"
         val fallbackTry = Try(unsafeMethod).orElse(Try(backUpMethod))
         println(fallbackTry)

         // design the apis in better way
         def betterUnsafeMethod: Try[String] = Failure(new RuntimeException("Better Unsafe method"))
         def betterBackupMethod: Try[String] = Success("Better valid result")
         val betterFallback = betterUnsafeMethod orElse betterBackupMethod
         println(betterFallback)

         // map, flatMap, filter
         println(aSuccess.map(_ * 3))
         println(aSuccess.flatMap(x => Success(x * 10)))
         println(aSuccess.filter(_ > 10)) // this will turn success into failure

         // since map, flatMap, filter are available so will be for-comprehension
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Mawazo

Mostly technology with occasional sprinkling of other random thoughts

amintabar

Amir Amintabar's personal page

101 Books

Reading my way through Time Magazine's 100 Greatest Novels since 1923 (plus Ulysses)

Seek, Plunnge and more...

My words, my world...

ARRM Foundation

Do not wait for leaders; do it alone, person to person - Mother Teresa

Executive Management

An unexamined life is not worth living – Socrates

javaproffesionals

A topnotch WordPress.com site

thehandwritinganalyst

Just another WordPress.com site

coding algorithms

"An approximate answer to the right problem is worth a good deal more than an exact answer to an approximate problem." -- John Tukey

%d bloggers like this: