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
}
}