【Scala】オプション型

前回(【Scala】リストのリスト、対と組 - seconの日記)の続き

今回は10.オプション型

オプション型(Option)


Scalaでは値が存在しない可能性がある場合などにOption型を用いる。
例えば以下のようなMapがあるとき

scala> val ageMap = Map("Taro"->21, "Jiro"->19)
ageMap: Map[String,Int] = Map(Taro -> 21, Jiro -> 19)



get(p)でキーが p の値が a の場合、Some(a)を返し、存在しない場合はNoneを返す

scala> ageMap.get("Taro")
res: Option[Int] = Some(21)

scala> ageMap.get("Saburo")
res: Option[Int] = None



Some(a)に対してgetで値を取り出せる。Noneに対してgetを使用すると例外が発生する

scala> ageMap.get("Taro").get
res12: Int = 21

scala> ageMap.get("Saburo").get
java.util.NoSuchElementException: None.get //例外発生



Some(a)かNoneが返されるかの区別にはisEmptyを使う

scala> ageMap.get("Taro").isEmpty
res16: Boolean = false

scala> ageMap.get("Saburo").isEmpty
res17: Boolean = true  //Noneならtrueが返される



Some(a)は長さ1のリスト、None は空リストと同様の扱い。

scala> ageMap.get("Taro").filter(_>=20) //filterを使った例
res: Option[Int] = Some(21)  

scala> ageMap.get("Saburo").filter(_>=20)
res: Option[Int] = None  //Boolean型ではない

scala> ageMap.get("Jiro").map(_+1)  //mapも使える
res24: Option[Int] = Some(20)



文字列のリストに適用した例

scala> val names = Seq("Taro","Jiro","Saburo")
names: Seq[String] = List(Taro, Jiro, Saburo) 

scala> names.map(p => ageMap.get(p).filter(_ >= 20))  
res: Seq[Option[Int]] = List(Some(21), None, None)

scala> names.map(p => ageMap.get(p).map(_+1).filter(_ >=20))
res: Seq[Option[Int]] = List(Some(22), Some(20), None) //来年は20歳以上のリスト、みたいな



リスト扱いなので、連結も出来る

scala> ageMap.get("Taro") ++ ageMap.get("Jiro")
res: Iterable[Int] = List(21, 19)  //Iterableとなる点に注意

scala> ageMap.get("Taro") ++ ageMap.get("Saburo")
res: Iterable[Int] = List(21)  //None=空リストなので連結されない

scala> names.map(p => ageMap.get(p)).flatten
res: Seq[Int] = List(21, 19)  //値のあるものだけを連結することも

Iterableはコレクション階層の上から二番目に位置するトレイト(一番上はTraversable)。


for や forMap を用いた例。

scala> names.flatMap(p => ageMap.get(p))
res: Seq[Int] = List(21, 19)

>|scala|
scala> for(p<-names;a<-ageMap.get(p))yield a+1  //39bytes
res: Seq[Int] = List(22, 20)

>|scala|
scala> names.flatMap(p=>ageMap.get(p).map(_+1))  //40bytes
res: Seq[Int] = List(22, 20)



このように、値の有無に関わらず統一的な処理が可能。

どうでもいいけど適当に作った式がまるっきり練習問題の答えでわろた