やりたいこと
複数の処理を直列で行い、すべて成功していれば次の処理へ ってよく書きますよね
一般的な手続き型言語であればこんな感じでしょうか
if(処理A && 処理B && 処理C){
処理X
}
処理Aの結果を処理Bで処理し、結果Bを最後の処理Xで使いたい場合とかどうしましょう
Scalaでcase文だとこんな感じでしょうか
処理A match {
case Right(結果A)=>{
処理B(結果A) match {
case Right(結果B) =>{
if(処理C){
処理X(結果B)
}
}
}
}
}
{}地獄。。。
#こんな風に書けたら見通しがいいです
(for{
結果A<-処理A
結果B<-処理B(結果A)
結果C<-処理C
} yield Success(結果B)).merge match {
//処理A,処理B,処理Cがすべて成功した場合、結果Bを処理Xで実行する。
case Success(結果B)=>処理X(結果B)
//処理A,処理B,処理Cのどれかが失敗した場合、エラー結果を出力する。
case error:Failure=>println(error)
}
実際書いてみる。
1.下準備
//sealed 基底クラス
sealed abstract class BaseResult
//Success(BaseResultを拡張)
case class Success(message:String) extends BaseResult
//Failure (BaseResultを拡張)
abstract class Failure extends BaseResult
//case object を使って各エラーを定義(Failureを拡張)
case object Error1 extends Failure
case object Error2 extends Failure
2.処理を定義
def func_a:Either[Failure,String]={Right("A")}//処理A
def func_b(str:String):Either[Failure,String]={Right(str+"B")}//処理B
def func_c:Either[Failure,String]={Right("C")}//処理C
def func_c_error:Either[Failure,String]={Left(Error1)}//処理C失敗
def func_x(str:String):Unit={println("すべて成功:%s".format(str))}//処理X
3.結果
すべて成功
scala> (for{
| resultA<-func_a.right //成功
| resultB<-func_b(resultA).right //成功
| resultC<-func_c.right //成功
| } yield Success(resultB)).merge match {
| case Success(x)=>func_x(x) //←
| case x:Failure=>println(x)
| }
すべて成功:AB
一部失敗
scala> (for{
| resultA<-func_a.right //成功
| resultB<-func_b(resultA).right //成功
| resultC<-func_c_error.right //失敗
| } yield Success(resultB)).merge match {
| case Success(x)=>func_x(x)
| case x:Failure=>println(x) //←
| }
Error1
最後に
基本形として覚えておきたい。