Skip to content

Instantly share code, notes, and snippets.

@tksugimoto
Last active June 11, 2017 10:37
Show Gist options
  • Save tksugimoto/cd28ba3bdabc39cf24735f901810319b to your computer and use it in GitHub Desktop.
Save tksugimoto/cd28ba3bdabc39cf24735f901810319b to your computer and use it in GitHub Desktop.
Scala Either snippet
// Either: LeftとRightのどちらかを取りうるもの(OptionはSome(x)とNoneのどちらかを取りうるもの)
// 嬉しさ:OptionはSome(x), Noneだったが、EitherはRight(x), Left(y)になり、None相当のときに情報を持てる(エラー情報を持つことが多い)
// Scala 2.11
case class User(id: Int)
def findUserById(id: Int): Either[String, User] = {
id match {
case 2 => Left("存在しない")
case 5 => Left("バンされた")
case _ => Right(User(id))
}
}
val userEither1: Either[String, User] = findUserById(1) // Right(User(1))
val userEither2: Either[String, User] = findUserById(2) // Left("存在しない")
val userEither3: Either[String, User] = findUserById(3) // Right(User(3))
val userEither4: Either[String, User] = findUserById(4) // Right(User(4))
val userEither5: Either[String, User] = findUserById(5) // Left("バンされた")
"================================== パターンマッチ =================================="
userEither1 match {
case Left(msg: String) => println(msg)
case Right(user: User) => println(user)
} // User(1)
userEither2 match {
case Left(msg: String) => println(msg)
case Right(user: User) => println(user)
} // "存在しない"
case class Result(message: String)
def user2result(userEither: Either[String, User]): Result = userEither match {
case Left(msg: String) => Result(s"[Userは見つからなかった] 理由: ${msg}")
case Right(user: User) => Result(s"id: ${user.id}のUserが見つかった")
}
user2result(userEither3) // Result("id: 3のUserが見つかった")
user2result(userEither4) // Result("id: 4のUserが見つかった")
user2result(userEither5) // Result([Userは見つからなかった] 理由: バンされた)
"================================== Option化 =================================="
// 情報が減るのであまり使われない気がする
// .rightでRightをSome側にできる
userEither1.right.toOption // Some(User(1))
userEither2.right.toOption // None
userEither3.right.toOption // Some(User(3))
userEither4.right.toOption // Some(User(4))
userEither5.right.toOption // None
// .leftでLeftをSome側にできる(あまり使われない気がする)
userEither1.left.toOption // None
userEither2.left.toOption // Some("存在しない")
userEither3.left.toOption // None
userEither4.left.toOption // None
userEither5.left.toOption // Some("バンされた")
"================================== map処理 =================================="
// RightのときにUser情報からidを取り出す
val rightMappedUser1: Either[String, Int] = userEither1.right.map((user: User) => user.id) // Right(1)
val rightMappedUser2: Either[String, Int] = userEither2.right.map((user: User) => user.id) // Left("存在しない")
val rightMappedUser3: Either[String, Int] = userEither3.right.map((user: User) => user.id) // Right(3)
// Leftのときにエラーメッセージの長さを先頭に追加
val leftMappedUser1: Either[String, User] = userEither1.left.map((msg: String) => s"${msg.length}: ${msg}") // Right(1)
val leftMappedUser2: Either[String, User] = userEither2.left.map((msg: String) => s"${msg.length}: ${msg}") // Left("5: 存在しない")
val leftMappedUser3: Either[String, User] = userEither3.left.map((msg: String) => s"${msg.length}: ${msg}") // Right(3)
// 両方
val leftRightMappedUser1: Either[String, Int] = userEither1
.left.map((msg: String) => s"${msg.length}: ${msg}")
.right.map((user: User) => user.id) // Right(1)
val leftRightMappedUser2: Either[String, Int] = userEither2
.left.map((msg: String) => s"${msg.length}: ${msg}")
.right.map((user: User) => user.id) // Left("5: 存在しない")
val leftRightMappedUser3: Either[String, Int] = userEither3
.left.map((msg: String) => s"${msg.length}: ${msg}")
.right.map((user: User) => user.id) // Right(3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment