Scala学習【エラー処理に使う型】
前回に引き続きScalaの学習。今回はエラー処理で使うであろう戻り値をラップする型について。
Option型
- 値をひとつだけ入れることができる
- 2種類の形を持っている
- Some(x) 値があるときの形
- None 値がないときの形
- 値があったりなかったりする値を表現するときに使う
- エラー内容を表現できないので、エラー処理では使わない
// Some: 値があるとき scala> val some: Option[String] = Option("hoge") some: Option[String] = Some(hoge) scala> some.get res7: String = hoge // None: 値がないとき scala> val none: Option[String] = Option(null) none: Option[String] = None scala> none.get java.util.NoSuchElementException: None.get at scala.None$.get(Option.scala:349) at scala.None$.get(Option.scala:347) ... 29 elided
None
を get
したときの例外は getOrElse
メソッドを使えば回避できる
scala> option.getOrElse("値がありません") res3: String = 値がありません
パターンマッチを使って処理することもできる
scala> val some: Option[String] = Option("hoge") some: Option[String] = Some(hoge) scala> some match { | case Some(str) => println(str) // Someの中身をstrという変数に束縛している | case None => print("None") | } hoge
Optionはコレクションの性質を持っているので、例えばmapを使える
// Some の場合 scala> Some(3).map(_ * 3) res10: Option[Int] = Some(9) // None の場合は関数を適用しても None のまま scala> val none: Option[Int] = None none: Option[Int] = None scala> none.map(_ * 3) res11: Option[Int] = None // foldメソッドを使えばデフォルト値を指定できる scala> none.fold(0)(_ * 3) res12: Int = 0
Either型
- Option型と違い、エラー時に任意のエラーの種類まで取得できる
- RightとLeftの2つの値を持つ
- Right: 正常な値
- Left: エラー値
scala> val right: Either[String, Int] = Right(123) right: Either[String,Int] = Right(123) scala> val left: Either[String, Int] = Left("abc") left: Either[String,Int] = Left(abc) // パターンマッチもできる scala> right match { | case Right(i) => println(i) | case Left(s) => println(s) | } 123
Option型と同様にmapメソッドを持っている
Either型の左右が平等に扱われる場合、mapメソッドはどちらに適用されるのだろう。となるが、暗黙的にrightを優先される(Scala2.12から)
Scala2.12より前は平等に扱われるため、RightProjection
型に変換する必要があった
// サジェストされるメソッドを確認 scala> right. canEqual filterOrElse forall isLeft joinRight merge productIterator swap toTry contains flatMap foreach isRight left productArity productPrefix toOption exists fold getOrElse joinLeft map productElement right toSeq // Scala2.12 scala> right.map(_ * 3) res0: scala.util.Either[String,Int] = Right(369) // Scala2.12より前 scala> right.right res1: scala.util.Either.RightProjection[String,Int] = RightProjection(Right(123)) scala> right.right.map(_ * 3) res0: scala.util.Either[String,Int] = Right(369)
Try型
- 2つの値をとる
- Success: 正常な値
- Failure: エラー値(ただし
Throwable
というException
のスーパークラスしか入れられない)
- applyで生成する際に例外をキャッチし、Failureにする
- NonFatal(致命的でない)という種類の例外だけキャッチする
scala> import scala.util.Try import scala.util.Try scala> val failure: Try[Int] = Try(throw new RuntimeException("to be caught")) failure: scala.util.Try[Int] = Failure(java.lang.RuntimeException: to be caught) scala> val success = Try(3) success: scala.util.Try[Int] = Success(3)
参考