ScalaのOption型について

Scalaにはオプションの値のためのOption型がある。
今回はこのOption型についてブログに書く。

なぜnullではなくOptionなのか?

他の言語ではnullを使うことが多いけど、Scalaではnullは使わない。使うことはできるけど暗黙の了解というかOptionを使うことが推奨されている。
このおかげでnullチェックの煩わしさが減る。Option型の変数として示すことでnullになる可能性のあるということをコードの読み手に伝えることができる。

Optionとは?

Optionとは値があるかどうかわからない状態を表すための型です。
Optionのサブクラスには値があるときのSome(value)と、値がないことを表すNoneがあります。
Optionは値がnull以外の時あるときはSome(value)、値がない場合nullの場合はNoneを返します。

Optionの値を取り出す方法

Optionの値を取り出す例を見てみます。

scala> val something : Option[String] = Option("test")
something: Option[String] = Some(test)

//Optionのgetメソッド
//getメソッドは値があるわかっているときに使う(逆に確かではない時はgetOrElseメソッドなどを使う)
scala> val result = something.get
result: String = test

//OptionのisEmptyメソッド
scala> val result = something.isEmpty
result: Boolean = false

//Noneのとき
scala> val none : Option[String] = None
none: Option[String] = None

scala> none.get
java.util.NoSuchElementException: None.get
  at scala.None$.get(Option.scala:322)
  at scala.None$.get(Option.scala:320)
  ... 32 elided

//getOrElseメソッドでnullの場合を指定することも可能
scala> none.getOrElse("Null")
res3: String = Null

Mapのgetメソッドで引数のキーに対応する値あるかどうか下のように確認できます。

scala> val fruitsColor = Map("apple" -> "red", "banana" -> "yellow", "mango" -> "orange")
fruitsColor: scala.collection.immutable.Map[String,String] = Map(apple -> red, banana -> yellow, mango -> orange)

//Mapのgetメソッド
scala> fruitsColor get "apple"
res1: Option[String] = Some(red)

scala> fruitsColor get "melon"
res2: Option[String] = None


OptionをパターンマッチでSomeまたはNoneにマッチさせることで値を取り出すことも可能です。

//パターンマッチでOptionの値を取得する
scala> def something(x: Option[String]) = x match {
     | case Some(value) => value
     | case None => "empty"
     | }
something: (x: Option[String])String

scala> something(Option("test"))
res1: String = test

scala> something(None)
res2: String = empty

Option確かに便利です。
他の言語でもこれ使えたらいいのに!

追記
Optionのforeachメソッドとmapメソッドも便利ということで調べてみました。

//Optionは基本値があるかないかの時に使う(同じ属性の値が複数の時はListを使用)
scala> val myPhone = Option("iPhone5S")
myPhone: Option[String] = Some(iPhone5S)

//Optionのforeachメソッド
scala> myPhone.foreach(println)
iPhone5S

//Noneの場合はなにもしません。
scala> None.foreach(println)
//mapメソッド
scala> myPhone.map { x => x.size }
res1: Option[Int] = Some(8)

scala> myPhone.map { x => x.length }
res2: Option[Int] = Some(8)

scala> myPhone.map { x => x.toString }
res3: Option[String] = Some(iPhone5S)

scala> None.map { x => x.toString }
res4: Option[String] = None

参考記事
ScalaのOptionステキさについてアツく語ってみる - ( ꒪⌓꒪) ゆるよろ日記


Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版

Guide to ScalaーScalaプログラミング入門

Guide to ScalaーScalaプログラミング入門