Вопрос по – Почему снятие исключения является побочным эффектом?

38

Согласно записи в Википедии дляпобочный эффектВозникновение исключения является побочным эффектом. Рассмотрим эту простую функцию Python:

def foo(arg):
    if not arg:
        raise ValueError('arg cannot be None')
    else:
        return 10

Вызывая его сfoo(None) всегда будет встречаться с исключением. Тот же вход, тот же выход. Это ссылочно прозрачно. Почему это не чистая функция?

Переезд, чтобы открыть это, безусловно, вопрос, в то время как более теоретический характер по-прежнему актуален для этого сайта. Woot4Moo
Это кажется вполне подходящим для SO. Don Stewart
Следует перенести вSoftware Engineering Daenyth
Исключение не просто возвращается как возвращаемое значение. Sjoerd

Ваш Ответ

4   ответа
32

если вы наблюдаете исключение и на его основе принимаете решение, которое меняет поток управления. Фактически выбрасывание значения исключения является прозрачным по ссылкам - оно семантически эквивалентно не прекращению или другому так называемомунижние значения.

Если (чистая) функция неВсего, тогда это оценивает к нижнему значению. То, как вы кодируете нижнее значение, зависит от реализации - это может быть исключением; или не прекращение, или деление на ноль, или какой-то другой сбой.

Рассмотрим чистую функцию:

 f :: Int -> Int
 f 0 = 1
 f 1 = 2

Это не определено для всех входов. Для некоторых это оценивается снизу. Реализация кодирует это, бросая исключение. Это должно быть семантически эквивалентно использованиюMaybe или жеOption тип.

Теперь вы нарушаете прозрачность ссылок только тогда, когдаobserve минимальное значение и принимать решения на его основе, что может привести к недетерминированности, поскольку может быть выдано много разных исключений, и вы не можете знать, какое именно. Так что по этой причине ловить исключения вIO монада в Haskell, при генерации так называемого& Quot; неточным & Quot; исключения можно сделать чисто.

Так что это просто неправда, что повышение исключения является побочным эффектом как таковым. Проблема в том, можете ли вы изменить поведение чистой функции на основе исключительного значения - тем самым нарушив ссылочную прозрачность - вот в чем проблема.

Интересно, что я всегда думал, что определение RT было бы, если бы вы могли заменить выражение на его значение, и у вас не может быть значения «выдает исключение A».
@ Джед Уэсли-Смит Вы правы. Когда функция вызывает исключение, она не может вернуть значение и нарушает прозрачность ссылок. Неверное представление о том, что RT нарушается только при обработке исключения, удобно тем, что позволяет передавать беспорядочные детали полного моделирования домена вызывающим функциям, которые вызывают исключения.
4

(например, вызов функции) результатом самого вычисления, что вы не можете сделать, если ваша функция вызывает исключение. Это потому, что исключения не принимают участие в вычислениях, но их нужно отлавливать!

Ну, это может быть правдой, если нет исключений. Но если таковые имеются, вы можете просто вызвать исключение вместо выполнения функции (аналог для возврата значения вместо выполнения функции).
11

"In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world"

Состояние, которое оно изменяет, является завершением программы. Чтобы ответить на ваш другой вопрос о том, почему это не чистая функция. Функция не является чистой, потому что создание исключения завершает программу, поэтому имеет побочный эффект (ваша программа заканчивается).

Хорошо. Я куплю его, если мы различаем общие и частичные функции.
Дон: На самом деле, прекращение (частичное) частоis рассматривается эффект, особенно когда люди заинтересованы в сборе изоморфизма Карри / Ховарда и используют типы в качестве предложений.
Завершение не является эффектом. Это не состояние, которым можно поделиться. Многие чистые частичные функции не заканчиваются или определены только частично. Они все еще чисты. Например, деление на ноль - это чистая функция, которая не выполняется.
5

это зависит только от типа создаваемого исключения. Хорошее практическое правило заключается в том, что если исключение вызывается кодом, оно является чистым, но если оно вызывается аппаратным обеспечением, то оно обычно должно классифицироваться как не чистое.

Это можно увидеть, посмотрев на то, что происходит, когда аппаратное обеспечение вызывает исключение: сначала подается сигнал прерывания, затем начинает выполняться обработчик прерывания. Проблема здесь в том, что обработчик прерываний не был ни аргументом вашей функции, ни заданным в вашей функции, а глобальной переменной. Каждый раз, когда глобальная переменная (состояние) читается или записывается, у вас больше нет чистой функции.

Сравните это с исключением, которое возникает в вашем коде: вы создаете значение Exception из набора известных локально ограниченных аргументов или констант, и вы & quot; throw & quot; результат. Здесь не используются глобальные переменные. Процесс создания исключения по сути является синтаксическим сахаром, предоставляемым вашим языком, он не вводит недетерминированного или не чистого поведения. Как сказал Дон «Семантически, он должен быть эквивалентен использованию типа Maybe или Option», что означает, что он также должен иметь все те же свойства, включая чистоту.

Когда я сказал, что повышение аппаратного исключения - это «обычно» классифицируется как побочный эффект, это не всегда должно быть так. Например, если компьютер, на котором работает ваш код, не вызывает прерывание при возникновении исключения, а вместо этого помещает специальное значение в стек, то он не классифицируется как не чистый. Я считаю, что ошибка NAN IEEE с плавающей запятой генерируется с использованием специального значения, а не прерывания, поэтому любые исключения, возникающие при выполнении математических операций с плавающей запятой, могут быть классифицированы как побочные эффекты, так как значение не читается из какого-либо глобального состояния, но является константа, закодированная в FPU.

Рассматривая все требования, предъявляемые к чистому куску кода, исключениям, основанным на коде, и синтаксическому сахарному методу оператора throw, отметьте все поля, они не изменяют никакого состояния, не имеют никакого взаимодействия со своими вызывающими функциями или чем-либо вне их вызова, и они прозрачны по ссылкам, но только после того, как компилятор освоит ваш код.

Как и во всех чистых и не чистых обсуждениях, я исключил любое понятие времени выполнения или операций с памятью и действовал в предположении, что любая функция, которая МОЖЕТ быть реализована чисто, реализована исключительно независимо от ее фактической реализации. У меня также нет доказательств заявления об исключении IANE с плавающей точкой NAN.

Похожие вопросы