値を安全にラップして、操作をつなげられる型のこと
null
が多用され、その扱いでバグが多発するnull
の代わりにOption
型を使い、安全に値の有無を表現するSome("")
""
が「実際の値」Some("hello")
は「値が’hello’で存在する」ことを表すNone
()
は付けない基本例
def findName(id: Int): Option[String] = {
if (id == 1) Some("Alice")
else None
}
val nameOpt = findName(2)
nameOpt match {
case Some(name) => println(s"Name found: $name")
case None => println("No name found")
}
使い方例1
def findUser(id: Int): Option[String] = {
if (id == 1) Some("Alice")
else None
}
val user1 = findUser(1) // Some("Alice")
val user2 = findUser(2) // None
使い方例2
def findName(id: Int): Option[String] = {
if (id == 1) Some("Alice")
else None
}
val nameOpt = findName(2)
nameOpt match {
case Some(name) => println(s"Name found: $name")
case None => println("No name found")
}
参照:サンプルコード
.map
:値があるときだけ関数を適用
val nameOpt = Some("Alice")
val upper = nameOpt.map(n => n.toUpperCase) // Some("ALICE")
None
だった場合はスルーされ、結果もNone
のまま
.getOrElse(default)
:値がないときのデフォルトを指定
val result = nameOpt.getOrElse("No name") // "Alice"
val noneOpt: Option[String] = None
val fallback = noneOpt.getOrElse("No name") // "No name"
.flatmap
fold
参照:サンプルコード
複数のOption
を連続的に使いたいとき、ネストせずに読みやすく書くことができる
def getUser(id: Int): Option[String] = Some("ユーザー")
def getEmail(name: String): Option[String] = Some(s"$name@example.com")
val result: Option[String] = for {
name <- getUser(1)
email <- getEmail(name)
} yield s"Send to: $email"
println(result.getOrElse("No email found"))
None
が1つでもあれば全体がNone
になるSome
ならばその中身を抽出して順に使えるyield
の中が最終結果になる参照:サンプルコード
val result: Either[String, Int] = Right(42)
val error: Either[String, Int] = Left("Error occurred")
Right
:成功(正常系)Left
:失敗(異常系)活用例
val res: Either[String, Int] = Right(42)
res match {
case Right(v) => println(s"Success: $v")
case Left(e) => println(s"Error: $e")
}
参照:サンプルコード
map
flatMap
fold
複数のEither
を連続的に使いたいときに、ネストせずに読みやすく書くことができる
def getUser(id: Int): Either[String, String] = Right("ユーザー")
def getEmail(name: String): Either[String, String] = Right(s"$name@example.com")
val result: Either[String, String] = for {
name <- getUser(1)
email <- getEmail(name)
} yield s"Send to: $email"
println(result) // Right(Send to: ユーザー@example.com)
Left
が1つでも出たらその時点で打ち切られる(早期return)Right
同士ならば、合成されて最終的にRight(結果)
になる参照:サンプルコード
import scala.concurrent._
import ExecutionContext.Implicits.global
import scala.util.{Success, Failure}
val f: Future[Int] = Future {
// 重い計算やI/O処理を非同期に実行
Thread.sleep(1000)
42
}
f.onComplete {
case Success(value) => println(s"Got the result: $value")
case Failure(e) => println(s"Failed with $e")
}
Future { ... }
ブロック内の処理は別スレッドで非同期実行onComplete
で成功・失敗をハンドルimport ExecutionContext.Implicits.global
でスレッドプールの設定が必要Await.result
で同期的に結果を待てるが、多用は避ける参照:サンプルコード
onComplete
:結果に応じた処理を登録map
/flatMap
:非同期チェーン処理recover
/recoverWith
:エラーを補正