3

Имеется 3 метода возвращающие Either, которые необходимо вызывать последовательно и если предыдущий вернул Right. Вернуть надо только результат последнего Either. Как правильно их обработать, чтобы не потерять Left, в случае возникновения ошибки и чтобы не было вложенности вида Either[Either[Either...]]].

def doSmth1: Either[Exception, String] = {}
def doSmth2: Either[Exception, String] = {}
def doSmth3: Either[Exception, String] = {}

Пробовал обрабатывать так:

doSmth1.map(s1 => {/** do something */
  doSmth2.map({
    doSmth3.map({
      //do something
    })
  })
})

Но вложенность получается Either[Either[Either...]]]. Можно обрабатывать через for comprehensions:

for (
  s1 <- doSmth1
  s2 <- doSmth2
  s3 <- doSmth3
) yield

Как вычислить Either без получения вложенностей?

  • Так чем не устраивает вариант с for? С ним вложенности не будет – extrn Jul 20 '20 at 22:30
  • @extrn я не совсем был уверен, что при возникновении Left, for comprehensions выбросит его. – Konstantin Jul 21 '20 at 07:10
  • 2
    for comprehension это синтаксический сахар для применения метода flatMap (в основном), а в нем у Either прописано как раз нужное вам поведение. – extrn Jul 21 '20 at 08:31

1 Answers1

4

Чтобы не было вложенности, можно воспользоваться методом Either.flatten.

doSmth1.map(s1 =>
  doSmth2.map(s2 =>
    doSmth3.map(s3 => /* do something with s1, s2, */ s3)
  ).flatten
).flatten

А еще лучше методом, который объединяет map и flatten

doSmth1.flatMap(s1 =>
  doSmth2.flatMap(s2 =>
    doSmth3.map(s3 => /* do something with s1, s2, */ s3)
  )
)

Примерно такой код и сгенерирует компилятор при использовании следующей конструкции

for {
  s1 <- doSmth1
  s2 <- doSmth2
  s3 <- doSmth3
} yield /* do something with s1, s2, */ s3

Для вашего же случая, когда s1 и s2 не важны, а s3 используется без изменения, получаем следующее выражение, применив тождественные преобразования

doSmth1 flatMap (_ => doSmth2) flatMap (_ => doSmth3)

Можете выбрать любой вариант, но я бы остановился на for comprehension из за его простоты.

extrn
  • 10,941