Я использую Either
большую часть времени, а не исключения.Я обычно использую исключения, как вы делали, или каким-то подобным образом, когда поток управления должен идти в обратном направлении, в какую-то далекую точку, а в остальном ничего толкового делать не приходится.Однако, когда исключения могут обрабатываться довольно локально, я вместо этого
def myMethod(...): Either[String,ValidatedInputForm] = {
...
if (!someHelper(...)) Left("Agree button not checked")
else Right(whateverForm)
}
, а затем, когда я вызываю этот метод, я могу
myMethod(blah).fold({ err =>
doSomething(err)
saneReturnValue
}, { form =>
foo(form)
form.usefulField
})
или сопоставлять на Left(err)
против Right(form)
, или другие разные вещи.
Если я не хочу прямо сейчас обрабатывать ошибку, а вместо этого хочу обработать возвращаемое значение, я
myMethod(blah).right.map{ form =>
foo(form)
bar(form)
}
и яполучите Either
с сообщением об ошибке, неизменным как Left
, если оно было сообщением об ошибке, или с результатом { foo(form); bar(form) }
как Right
, если все в порядке.Вы также можете связать обработку ошибок с помощью flatMap
, например, если вы хотите выполнить дополнительную проверку до сих пор правильных значений и отклонить некоторые из них, вы можете
myMethod(blah).right.flatMap{ form =>
if (!checkSomething(form)) Left("Something didn't check out.")
else Right(form)
}
Это такая обработкаэто делает использование Either
более удобным (и обычно более эффективным, если исключения являются общими), чем исключения, поэтому я использую их.
(На самом деле, во многих случаях мне все равно почему что-то пошло не так, только , что пошло не так, и в этом случае я просто использую Option
.)