エラー処理によるコードの分岐を減らしたい場合、Eitherを使うとよい。

Eitherの使い方

Either[A, B] は、AまたはBを返す型である。

Eitherは通常Either[(エラー情報), (結果)]の形で使われる。例えばデータ処理が成功した場合はその結果を用いて引き続きの処理を行いたいが、エラーの場合は何もせず次のコードにエラーだけを伝えたい場合がある。

Eitherから値を取り出すには、left, rightの値に対してmap, flatMapなどを用いる。例えば、Either.right map { ... }とすると、値の内容がRight型の場合はmap内の関数を適用し、Leftの型の場合はmapの処理を無視してLeftの内容(この場合はエラー情報を)をそのまま返す。

具体例

# 文字列がIntに変換できるならIntを、失敗した場合はExceptionを返す関数
scala> def parseInt(s:String) : Either[Exception, Int] =
  try Right(s.toInt) catch { case e:Exception => Left(e) } 
Parseint: (s: String)Either[Exception,Int]

# Intへの変換が成功。Rightを返す
scala> parseInt("128")
res5: Either[Exception,Int] = Right(128)

# 変換できない場合はLeftを返す
scala> parseInt("234A")
res6: Either[Exception,Int] = Left(java.lang.NumberFormatException: For input string: "234A")

# 値を取りだしてFloatに変換
scala> parseInt("49").right map { _.toFloat } 
res8: Product with Serializable with Either[Exception,Float] = Right(49.0)

# 結果がLeft(Exception)の場合は、toFloatは実行されずに、Exceptionを伝播する
scala> parseInt("ADF").right map { _.toFloat }
res9: Product with Serializable with Either[Exception,Float] = Left(java.lang.NumberFormatException: For input string: "ADF")

# Left(Exception)であれば、その内容を表示(getMessage) 
scala> parseInt("ADF").left map { _.getMessage } 
res11: Product with Serializable with Either[java.lang.String,Int] = Left(For input string: "ADF")

# 結果がRightの場合は、getMessageは実行されない
scala> parseInt("40").left map { _.getMessage }
res12: Product with Serializable with Either[java.lang.String,Int] = Right(40)

Eitherを使うことで、エラーを含んだデータであっても処理の流れを妨げないようにできる。

参考

comments powered by Disqus