Option型
• nullの不便さからの卒業 (さらばヌルポ)
• 値が存在しないかもしれない、という文脈を表
現 (Some or None)
Slide 9
Slide 9 text
val o: Option[String] = Some("Hello")
o: Option[String] = Some(Hello)
val o: Option[String] = None
o: Option[String] = None
val o: Option[String] = Option(null)
o: Option[String] = None
Slide 10
Slide 10 text
val m = Map("key" -> "value")
m: scala.collection.immutable.Map[String,String] =
Map(key -> value)
m.get("key")
Option[String] = Some(value)
m.get("hoge")
Option[String] = None
Slide 11
Slide 11 text
Option型
• undefチェックが型によって強制される
Slide 12
Slide 12 text
o.replace("Hello", "Hello World")
:12: error: value replace is not a member of
Option[String]
o.replace("Hello", "Hello World")
^
if (o.isDefined) {
o.get.replace("Hello", "Hello World")
}
Slide 13
Slide 13 text
Option型の値への
アクセス
• get
• getOrElse
• match式
Slide 14
Slide 14 text
val o = Some("Hello")
o: Some[String] = Some(Hello)
o.get
String = Hello
val o = None
o: None.type = None
o.get
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:347)
... 32 elided
Slide 15
Slide 15 text
val o = Some("Hello")
o: Some[String] = Some(Hello)
o.getOrElse("undefined")
res4: String = Hello
val o = None
o: None.type = None
o.getOrElse("undefined")
res5: String = undefined
Slide 16
Slide 16 text
val o: Option[String] = Some("Hello")
o: Option[String] = Some(Hello)
o match {
case Some(s) => s
case None => "undefined"
}
res1: String = Hello
1. mapを定義している型では
1個のジェネレータで構成されたfor式を使える
list.map(i => i * 2)
for {
i <- list
} yield i * 2
Slide 44
Slide 44 text
2. mapの他にflatMapも定義している型では、複数のジェネ
レータから構成されるfor式を使える
list.flatMap{ i =>
list2.map { j =>
i * j
}
}
for {
i <- list
j <- list2
} yield i * j
Slide 45
Slide 45 text
3. foreachを定義している型では、forループを使える
(ジェネレータは1個でも複数でもよい)
list.foreach { i =>
list2.foreach { j =>
println(i + j)
}
}
for {
i <- list
j <- list2
} {
println(i * j)
}
Slide 46
Slide 46 text
4. withFilterを定義している型では、for式の中でifで始
まるフィルター式を使える
list.withFilter(_ % 2 == 0).flatMap { i =>
list2.map { j =>
i * j
}
}
for {
i <- list
if i % 2 == 0
j <- list2
} yield i * j
Slide 47
Slide 47 text
自分で実装してみよう
Slide 48
Slide 48 text
case class Custom(v: String) {
def foreach(f: String => Unit): Unit = f(v)
}
for {
c <- Custom("Fukuoka")
} println(s“Hello $c”)
Slide 49
Slide 49 text
応用編: for式にパターンマッチが含まれる場合
Slide 50
Slide 50 text
val xs = List(
Seq(1, 2),
Seq(1, 2, 3),
Seq(1, 2, 3, 4)
)
for {
Seq(x, y, z) <- xs
} yield x + y + z
Slide 51
Slide 51 text
単純に下のように変換してしまうと実行時に
MatchErrorが発生してしまう
for {
Seq(x, y, z) <- xs
} yield x + y + z
xs.map {
case Seq(x, y, z) => x + y + z
}
しかし、上のfor式はエラーにならない。なぜか。
Slide 52
Slide 52 text
この場合はmapに加えてwithFilterが式展開される
for {
Seq(x, y, z) <- xs
} yield x + y + z
xs.withFilter {
case Seq(x, y, z) => true
case _ => false
}.map {
case Seq(x, y, z) => x + y + z
}
なのでmatchしないパターンは読み飛ばされる