ScalaでOption値を扱う場合、foreachやmapを使うことで、値が存在するときのみ処理を実行することができます。
戻り値が不要な場合はforeachを使用する
戻り値が不要な場合はforeachを使用することで安全にOption型から値を取り出せます。
def main(arts: Array[String]) : Unit = { Option(1).foreach(println) // =>1 None.foreach(println) // 何も表示しない(処理されない) }
foreachと言うとListなどを逐次的に処理するイメージがありますが、ScalaのOption型においては関係ありません。
実装も以下のように値があれば、引数として渡された関数を実行するだけになっています。
@inline final def foreach[U](f: A => U): Unit = { if (!isEmpty) f(this.get) }
戻り値が必要な時はmapメソッドを使う
戻り値が必要な時は、mapメソッドを使用します。
こちらもforeachと同様に、値がある時は処理し、なければNoneを返します。
def main(args: Array[String]) : Unit = { val optionInt = Option(1) val optionNoneInt : Option[Int] = None val res1 = optionInt.map(calc) val res2 = optionNoneInt.map(calc) println(res1) println(res2) } def calc(i : Int) : Int = { println("=== 計算実施 ===") println(s"i = ${i}") i * 2 } // 【出力結果】 // === 計算実施 === // i = 1 // Some(2) // None
値がある時は計算が行われ、無い場合はNoneになっていることがわかります。
ちなみにmapの実装は以下のようになっていました。
@inline final def map[B](f: A => B): Option[B] = if (isEmpty) None else Some(f(this.get))
関数がOption型を返す場合は、flatMapを使う
関数がOption型を返す場合、mapだとOption[Option[T]]のように、Optionが入れ子になってしまいます。
def main(args: Array[String]) : Unit = {
val optionInt = Option(1)
val res1 = optionInt.map(calc)
println(res1) // Some(Some(2))
}
def calc(i : Int) : Option[Int] = {
Option(i * 2)
}
その場合はflatMapを使用すれば入れ子になることを防げます。
def main(args: Array[String]) : Unit = {
val optionInt = Option(1)
val res1 = optionInt.flatMap(calc)
println(res1) // Some(2)
}
以下、flatMapの実装です。
optionでくるむかどうかがmapとの違いになっています。
@inline final def flatMap[B](f: A => Option[B]): Option[B] = if (isEmpty) None else f(this.get)
matchを使う
今まで紹介したものはmatchを使用して同じことができます。
def main(args: Array[String]) : Unit = { val optionInt = Option(1) // foreachの書き換え optionInt match { case Some(v) => println(v) case None => } // mapの書き換え val ans = optionInt match { case Some(v) => v * 2 case None => 2 } }