Skip to content
AgileLogics
6 min read

Option: No More null

Prerequisites: Collection operations, Match expressions

A value that might be missing has the type Option[A]: either Some(value) or None. Idiomatic Scala uses Option instead of null, so "might be missing" is visible in the type — and the compiler makes you handle it.

@main def options(): Unit =
  val emails = Map("ada" -> "ada@example.com")

  val found: Option[String] = emails.get("ada")
  val missing: Option[String] = emails.get("linus")
  println(found)
  println(missing)
  println("42".toIntOption)
  println("abc".toIntOption)
  println(List(1, 2, 3).find(_ > 5))
Some(ada@example.com)
None
Some(42)
None
None

Many standard methods return Option: Map.get, toIntOption, find, headOption, maxOption.

Getting the value out

@main def unwrap(): Unit =
  val maybeAge: Option[Int] = "36".toIntOption
  val noAge: Option[Int] = None

  println(maybeAge.getOrElse(0))
  println(noAge.getOrElse(0))

  val message = noAge match
    case Some(age) => s"Age is $age"
    case None      => "Age unknown"
  println(message)

  println(maybeAge.fold("unknown")(a => s"$a years"))
36
0
Age unknown
36 years

Transforming without unwrapping

Option works like a collection of zero or one elements, so map, filter, and flatMap work on it:

@main def chains(): Unit =
  def parse(s: String): Option[Int] = s.trim.toIntOption

  println(parse(" 21 ").map(_ * 2))
  println(parse("x").map(_ * 2))
  println(parse("15").filter(_ >= 18))
  println(parse("5").flatMap(n => if n > 0 then Some(100 / n) else None))

  val total = for
    a <- parse("10")
    b <- parse("32")
  yield a + b
  println(total)
Some(42)
None
None
Some(20)
Some(42)

A chain continues as long as values are present, and short-circuits to None as soon as one is missing — no if (x != null) checks.

Avoid .get

option.get returns the value but throws on None — it throws away the safety Option gives you. Use getOrElse, match, map, or fold.

Practice

Write safeDivide(a: Int, b: Int): Option[Int] that returns None when b is 0, and print the results for 10 / 2 and 10 / 0 with getOrElse(-1).

Show solution
def safeDivide(a: Int, b: Int): Option[Int] =
  if b == 0 then None else Some(a / b)

@main def divide(): Unit =
  println(safeDivide(10, 2).getOrElse(-1))
  println(safeDivide(10, 0).getOrElse(-1))
5
-1