scalaintermediate

Option Either and Try Error Handling

Handle errors functionally with Option, Either, and Try: map, flatMap, recover, and for-comprehensions.

scala
import scala.util.{Try, Success, Failure}

def parseAge(s: String): Option[Int] =
  s.toIntOption.filter(a => a >= 0 && a <= 150)

def divide(a: Double, b: Double): Either[String, Double] =
  if b == 0 then Left("Division by zero")
  else Right(a / b)

def readFile(path: String): Try[String] =
  Try(scala.io.Source.fromFile(path).mkString)

@main def run(): Unit =
  // === Option ===
  val age = parseAge("25")
  val invalid = parseAge("abc")

  println(age.getOrElse(0))      // 25
  println(invalid.getOrElse(0))  // 0

  age.foreach(a => println(s"Age: $a"))
  val doubled = age.map(_ * 2)
  println(s"Doubled: $doubled")  // Some(50)

  // flatMap chaining
  val result = parseAge("30").flatMap { a =>
    parseAge("20").map(b => a + b)
  }
  println(s"Sum: $result")  // Some(50)

  // for-comprehension (preferred)
  val total = for
    a <- parseAge("30")
    b <- parseAge("20")
    c <- parseAge("10")
  yield a + b + c
  println(s"Total: $total")  // Some(60)

  // === Either ===
  divide(10, 3) match
    case Right(v) => println(f"Result: $v%.4f")
    case Left(e)  => println(s"Error: $e")

  divide(10, 0) match
    case Right(v) => println(f"Result: $v%.4f")
    case Left(e)  => println(s"Error: $e")

  // Chain Either
  val computed = for
    a <- divide(100, 5)
    b <- divide(a, 4)
  yield b
  println(s"Chained: $computed")

  // === Try ===
  val parsed: Try[Int] = Try("42".toInt)
  val failed: Try[Int] = Try("abc".toInt)

  println(parsed.getOrElse(0))  // 42
  println(failed.getOrElse(0))  // 0

  // recover
  val recovered = failed.recover {
    case _: NumberFormatException => -1
  }
  println(s"Recovered: $recovered")  // Success(-1)

  // Try to Either
  val asEither: Either[Throwable, Int] = parsed.toEither
  println(s"As Either: $asEither")

  // Try to Option
  println(s"As Option: ${parsed.toOption}")
  println(s"Failed Option: ${failed.toOption}")

Use Cases

  • Null-safe programming with Option
  • Error handling without exceptions
  • Composable error chains with for-comprehensions

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.