В Scala 2.12, Either
смещен вправо, поэтому for-yield
справится с задачей.
for {
v1 <- Transformer1.transform("Whatever")
v2 <- Transformer2.transform(v1)
v3 <- Transformer3.transform(v2)
} yield {
v3
}
оценивается как Right(Whatever_One_Two_Three)
, а
for {
v1 <- Transformer1.transform("Whatever")
v2 <- TransformerError.transform(v1)
v3 <- Transformer3.transform(v2)
} yield {
v3
}
оценивается как Left(Error!!!!)
Однако, если вы хотите вернуть результат со всеми примененными преобразованиями, пока не будет достигнута ошибка, то есть
assert(transform("Whatever", tError) == Right("Whatever_One"))
тогда может сработать следующий рефакторинг функции transform
:
def transform(txt: String, transformers: Seq[Transformer]): Either[Error, String] = {
type Current = Either[Error, String]
type Previous = Either[Error, String]
def foldLeftWithEarlyReturn: Tuple2[Current, Previous] = {
transformers.foldLeft[Tuple2[Current, Previous]](Right(txt) , Right(txt)){
(result, t) => result match {
case ( Right(txt) , Right(previousTxt) ) => ( t.transform(txt) , Right(txt) )
case ( Left(error) , Right(previousTxt) ) => return ( Right(previousTxt), Left(error) )
case e => e
}
}
}
if (foldLeftWithEarlyReturn._1.isLeft)
foldLeftWithEarlyReturn._2 // this means last transformation in sequence resulted in Left, so return previous
else
foldLeftWithEarlyReturn._1
}