Skip to content

Instantly share code, notes, and snippets.

@martinloverse
Created March 20, 2017 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martinloverse/d7ddd5ddc2c5bce32a60e0b34d02d87a to your computer and use it in GitHub Desktop.
Save martinloverse/d7ddd5ddc2c5bce32a60e0b34d02d87a to your computer and use it in GitHub Desktop.
Scala For Comprehension Samples
import scala.concurrent.Future
val maybeName: Option[String] = Some("martin.lover")
val maybeAge: Option[Int] = Some(33)
case class Person(name:String, age:Int)
val person: Option[Person] =
for {
name <- maybeName
age <- maybeAge
} yield Person(name, age)
// このように展開される。
val person2: Option[Person] =
maybeName flatMap { name =>
maybeAge map { age =>
Person(name, age)
}
}
val maybeAddr: Option[String]
// こういうコードを書きがち。パターンマッチやflatMapのネストを発見したらforで書き換えるプルリクチャンス!
maybeName match {
case Some(name) => maybeAge match {
case Some(age) => maybeAddr match {
case Some(addr) => Person(name, age)
case None => None
}
case None => None
}
case None => None
}
(maybeName, maybeAge, maybeAddr) match {
case (Some(name), Some(age), Some(addr)) => Some(Person(name, age))
case _ => None
}
// map, flatMapを実装している型で上記のような表現が使える。
// コップ本23章 for式の再説に詳しい。
// 「文脈付きの値」flatMap3兄弟
// Option[A] あるかもしれないし、ないかもしれない値
val request: Map[String, String] = ???
case class Device(ua: String, ip: String, idfa: Option[String])
// ua, ipがなければDeviceはNone. idfaはないかもしれないのでなくてもOK
for {
ua <- request.get("ua")
ip <- request.get("ip")
idfa = request.get("idfa")
} yield Device(ua, ip, idfa)
// Future[A] 未来に取得できるかもしれないし、できないかもしれない値
case class Artist(name: String)
case class Song(name: String)
def searchArtist(name: String): Future[Artist] = ???
def searchSongs(artist: Artist): Future[Seq[Song]] = ???
import scala.concurrent.ExecutionContext.Implicits.global
val maybeSongs:Future[Seq[Song]] =
for {
// flatMapで展開されるということは、この書き方では順次実行になるので注意!
artist <- searchArtist("martin.lover")
songs <- searchSongs(artist)
} yield songs
// Either[A] 右(成功)かもしれないし、左(失敗)かもしれない値
def validateName(name: String): Either[String, String]
def validateAge(age: Int): Either[String, Int]
// Scala 2.12でEither が Right-Biasになった。no more `.right`!
val validPerson =
for {
name <- maybeName toRight "Name is Required"
age <- maybeAge toRight "Age is Required"
_ <- validateName(name)
_ <- validateAge(age)
} yield Person(name, age)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment