2012-05-22 2 views
27

Согласно записи wikipedia для side effect, повышение исключения представляет собой побочный эффект. Рассмотрим эту простую функцию питона:Почему возникает исключение побочного эффекта?

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

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

+0

Исключение не просто возвращается как возвращаемое значение. – Sjoerd

+4

Перемещение для повторного открытия это, безусловно, вопрос, в то время как более теоретический характер по-прежнему действителен для этого веб-сайта. – Woot4Moo

+0

Он должен быть перенесен на [programers.se] – Daenyth

ответ

10

От первой линии:

«В информатике, функция или выражение, как говорят, эффект боковой , если в дополнение к возвращению значения, он также изменяет некоторые состояние или имеет наблюдаемое взаимодействие с вызывающими функциями или внешний мир "

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

+0

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

+5

Дон: На ​​самом деле, бессрочное (акарифциальное) часто * считается *, считается эффектом, особенно там, где люди заинтересованы в сборе изоморфизма Карри/Говарда и использования в качестве предложений. –

+0

Хорошо. Я куплю его, если мы будем отличать полные и частичные функции. –

4

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

+1

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

24

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

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

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

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

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

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

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

+2

Интересно, я всегда думал, что определение RT было, если бы вы могли заменить выражение его значением, и вы не можете иметь значение «throws exception A». –

+0

@ JedWesley-Smith Вы правы. Когда функция вызывает исключение, она не возвращает значение и нарушает ссылочную прозрачность. Неправильное обозначение, что RT только сломано, когда обрабатывается исключение, удобно в том смысле, что оно позволяет нажимать беспорядочные детали полного моделирования домена на вызывающих функций, которые вызывают исключения. –

4

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

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

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

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

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

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