Contents

So what Options do I have?

Option types

Option type documentation:

Same names, a bit different API

Scala

In Scala the variants are called: None and Some which are final case subclasses of Option. I’ve noticed the subclassing has the nice property of helping in IDE to discover the variants (which is also the case, for example, for Try subclasses.

Rust

In Rust, the variants are also conveniently named Some and None.

API differences

(Scala vs Rust)

  • check presence: isDefined vs is_some
  • check absence: isEmpty vs is_none
  • transform value: map vs map
  • chain options: flatMap vs and_then
  • filter value: filter vs filter
  • default value: getOrElse vs unwrap_or
  • lazy default: getOrElse vs unwrap_or_else
  • alternative: orElse: vs or
  • to collection: toList vs iter
  • unsafe extract: get vs unwrap

Some specifics

Exercise

This is the example from Rust module option docs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) }

// A list of data to search through.
let all_the_big_things = [
    Kingdom::Plant(250, "redwood"),
    Kingdom::Plant(230, "noble fir"),
    Kingdom::Plant(229, "sugar pine"),
    Kingdom::Animal(25, "blue whale"),
    Kingdom::Animal(19, "fin whale"),
    Kingdom::Animal(15, "north pacific right whale"),
];

// We're going to search for the name of the biggest animal,
// but to start with we've just got `None`.
let mut name_of_biggest_animal = None;
let mut size_of_biggest_animal = 0;
for big_thing in &all_the_big_things {
    match *big_thing {
        Kingdom::Animal(size, name) if size > size_of_biggest_animal => {
            // Now we've found the name of some big animal
            size_of_biggest_animal = size;
            name_of_biggest_animal = Some(name);
        }
        Kingdom::Animal(..) | Kingdom::Plant(..) => ()
    }
}

match name_of_biggest_animal {
    Some(name) => println!("the biggest animal is {name}"),
    None => println!("there are no animals :("),
}

Let’s see how it would look like in scala:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

  private object Kingdom {
    final case class Plant(age: Int, name: String)
    final case class Animal(age: Int, name: String)
  }

  private val allTheBigThings = Vector(
    Kingdom.Plant(250, "redwood"),
    Kingdom.Plant(230, "noble fir"),
    Kingdom.Plant(229, "sugar pine"),
    Kingdom.Animal(25, "blue whale"),
    Kingdom.Animal(19, "fin whale"),
    Kingdom.Animal(15, "north pacific right whale"),
  )

  private def findBiggest(): Unit =  {
    var nameOfTheBiggestAnimal: Option[String] = None
    var sizeOfTheBiggestAnimal = 0
    allTheBigThings.foreach {
      case Kingdom.Animal(age, name) if age > sizeOfTheBiggestAnimal =>
        sizeOfTheBiggestAnimal = age
        nameOfTheBiggestAnimal = Some(name)
      case _ => ()
      // or:
      // case Kingdom.Animal(_,_) | Kingdom.Plant(_,_) => ()

    }

    nameOfTheBiggestAnimal match {
      case Some(name) => println(s"the bigest animal is $name")
      case None => println("There are no animals :(")
    }
  }

My notes:

  • in scala 2.x (before enum and named tuples) modelling two similar variants is possible either by
    • overriding abstract class Kingdom in case subclasses (would preserve class hierarchy) or
    • scoping case class Plant and case class Animal in object Kingdom which allows, well, scope access (which I like very much - this approach pushes towards providing explicit path to a class)
  • forEach allows to pattern match in anonymous function - without defining any binding to a iteration variable (big_thing in Rust snippet)
  • scala requires to declare a type of nameOfTheBiggestAnimal - without it the code does not compile; that’s because None value resolves to None.type and Some[String] is expected in assignment: compiler cries until I fixed that:

/en/posts/2026-03-17_so_what_options_do_i_have/none.jpg ./option_string.jpg

That’s all for today.

Happy coding!