Option: Some, None and no more null
The null reference is often called the billion-dollar mistake: any reference might be null, the type does not say so, and forgetting to check crashes at runtime. Scala code uses Option[A] instead. An Option[Int] is either Some(42) — a value is present — or None. Because the type is Option[Int] and not Int, the compiler will not let you use it as a number until you have decided what to do about None.
case class User(id: Int, name: String, email: Option[String])
val users = List(
User(1, "Asha", Some("[email protected]")),
User(2, "Ravi", None)
)
def findUser(id: Int): Option[User] = users.find(_.id == id)
@main def run(): Unit =
println(findUser(1))
println(findUser(9))
println(findUser(2).map(_.name))
println(findUser(2).flatMap(_.email))
println(findUser(1).flatMap(_.email).getOrElse("no email"))
println(findUser(9).isDefined)
val fromJava: String = null
println(Option(fromJava))
println(Option("x"))Some(User(1,Asha,Some([email protected])))
None
Some(Ravi)
None
[email protected]
false
None
Some(x)find already returns an Option. Wrapping a possibly-null value from a Java library with Option(...) turns null into None at the boundary, so the rest of your code never sees null. Some(null), by contrast, is a Some — always use Option(...) for Java values.
Add a third user with an email and print the domain part of user 3's email (.map(_.split("@")(1))), with "unknown" as the fallback.
Calling get on None
@main def run(): Unit =
val config = Map("host" -> "localhost")
val port = config.get("port").get
println(port)Exception in thread "main" java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:700)
at scala.None$.get(Option.scala:700)
at Main$package$.run(Main.scala:3)
at run.main(Main.scala:1)get on an Option means "I am sure this is a Some". When it is None, there is no value to return, so it throws — which is exactly the crash Option was meant to prevent. Calling .get gives up all the safety.
Say what should happen when the value is missing: getOrElse for a default, match or fold to handle both cases, or turn it into an Either with a helpful message.
@main def run(): Unit =
val config = Map("host" -> "localhost")
val port = config.get("port").getOrElse("8080")
println(port)