Является ли либо эквивалент проверенных исключений?
Начиная с Scala и читая о Either
Я естественно сравниваю новые понятия с тем, что знаю (в данном случае с Java). Есть ли отличия от концепции проверенных исключений и Either
?
В обоих случаях
- возможность сбоя явно аннотирована в методе (
throws
или возвращаясьEither
) - программист может обработать ошибку непосредственно, когда она возникает, или переместить ее вверх (возвращая снова
Either
) - есть способ сообщить звонившему о причине ошибки
Я полагаю, что кто-то использует для понимания Either
написать код, поскольку не было бы ошибки, подобной проверенным исключениям.
Интересно, я единственный новичок, у которого есть проблемы, чтобы увидеть разницу.
Спасибо
3 ответа
Either
может использоваться не только для исключений. Например, если вы хотите, чтобы пользователь либо вводил для вас ввод, либо указывал файл, содержащий этот ввод, вы могли бы представить его как Either[String, File]
,
Either
очень часто используется для обработки исключений. Основное различие между Either
и проверенные исключения в том, что поток управления с Either
всегда явно. Компилятор действительно не позволит вам забыть, что вы имеете дело с Either
; это не соберет Either
s из разных мест без вашего ведома, все, что возвращается, должно быть Either
и т.д. Из-за этого вы используете Either
не тогда, когда что-то необычное пойдет не так, а как обычная часть контроля выполнения программы. Также, Either
не захватывает трассировку стека, что делает его намного более эффективным, чем типичное исключение.
Еще одно отличие состоит в том, что исключения могут использоваться для потока управления. Нужно выпрыгнуть из трех вложенных циклов? Нет проблем - выведите исключение (без трассировки стека) и поймайте его снаружи. Нужно выпрыгнуть из пяти вложенных вызовов методов? Нет проблем! Либо не поставляет ничего подобного.
Тем не менее, как вы указали, есть ряд сходств. Вы можете передать информацию обратно (хотя Either
делает это тривиальным, в то время как проверенные исключения заставляют вас написать свой собственный класс для хранения любой дополнительной информации, которую вы хотите); Вы можете передать Either
или вы можете сложить его во что-то еще и т.д..
Итак, в заключение: хотя вы можете сделать то же самое с Either
и проверенные исключения в отношении явной обработки ошибок, они относительно различны на практике. Особенно, Either
делает создание и передачу различных состояний действительно простым, в то время как проверенные исключения хороши для обхода всего вашего обычного потока управления, чтобы, надеюсь, вернуться туда, где может быть разумно разрешено исключительное условие.
Либо эквивалентно проверенному исключению с точки зрения возвратной подписи, образующей исключительную дизъюнкцию. Результатом может быть выброшенное исключение X или A. Однако, выбрасывание исключения не эквивалентно возвращению одного - первое не является ссылочно прозрачным.
Если Scala's Either не является (по состоянию на 2.9) эквивалентом, это то, что тип возвращаемого значения имеет положительную предвзятость и требует усилий для извлечения / деконструкции Исключения, Either является беспристрастным; вам нужно явно запросить левое или правое значение. Это тема для некоторого обсуждения, и на практике это немного больно - рассмотрим следующие три вызова метода производства Either.
for {
a <- eitherA("input").right
b <- eitherB(a).right
c <- eitherC(b).right
} yield c // Either[Exception, C]
вам нужно вручную пропустить через RHS. Это может показаться не обременительным, но на практике это боль и несколько удивительно для новичков.
Да, Either
способ встраивать исключения в язык; где набор операций, которые могут потерпеть неудачу, может вызвать ошибку на каком-нибудь нелокальном сайте.
В дополнение к практическим вопросам, о которых упоминал Рекс, есть некоторые дополнительные вещи, которые вы получаете от простой семантики Either
:
Either
образует монаду; так что вы можете использовать монадические операции над наборами выражений, которые оцениваютEither
, Например, для оценки короткого замыкания без проверки результатаEither
находится в типе - так что одной проверки типа достаточно для отслеживания неправильной обработки значения
Если у вас есть возможность вернуть либо сообщение об ошибке (Left s)
или успешное значение Right v
Вы можете наложить исключения поверх, как просто Either
плюс обработчик ошибок, как это сделано для MonadError
в Хаскеле.