Erlang - Исключения

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

Обычно, когда в Erlang возникает исключение или ошибка, отображается следующее сообщение.

{"init terminating in do_boot", {undef,[{helloworld,start,[],[]}, 
{init,start_it,1,[]},{init,start_em,1,[]}]}}

Дамп сбоя будет записан в -

erl_crash.dump
init terminating in do_boot ()

В Erlang есть 3 типа исключений:

  • Error - Звонок erlang:error(Reason)завершит выполнение в текущем процессе и включит трассировку стека последних функций, вызванных с их аргументами, когда вы его поймаете. Это исключения, которые вызывают указанные выше ошибки времени выполнения.

  • Exists- Есть два вида выходов: «внутренние» и «внешние». Внутренние выходы запускаются вызовом функцииexit/1и остановить выполнение текущего процесса. Внешние выходы называютсяexit/2 и связаны с несколькими процессами в параллельном аспекте Erlang.

  • Throw- Бросок - это класс исключения, используемый для случаев, которые программист должен обработать. По сравнению с выходами и ошибками, они не несут никакого «краха этого процесса»! намерение позади них, а они контролируют поток. Поскольку вы используете броски, ожидая, что программист их обработает, обычно рекомендуется задокументировать их использование в модуле, использующем их.

А try ... catch - это способ оценить выражение, позволяя обработать успешный случай, а также обнаруженные ошибки.

Общий синтаксис выражения try catch следующий.

Синтаксис

try Expression of 
SuccessfulPattern1 [Guards] -> 
Expression1; 
SuccessfulPattern2 [Guards] -> 
Expression2 

catch 
TypeOfError:ExceptionPattern1 -> 
Expression3; 
TypeOfError:ExceptionPattern2 -> 
Expression4 
end

Выражение между try and ofсчитается защищенным. Это означает, что любое исключение, происходящее в этом вызове, будет перехвачено. Образцы и выражения междуtry ... of and catch вести себя точно так же, как case ... of.

Наконец, часть защелки - здесь вы можете заменить TypeOfErrorс помощью ошибки, выброса или выхода для каждого соответствующего типа, который мы видели в этой главе. Если тип не указан, предполагается выброс.

Ниже приведены некоторые ошибки и причины ошибок в Erlang.

ошибка Тип ошибки
Бадарг Плохой аргумент. Аргумент имеет неправильный тип данных или неправильно сформирован.
бадарис Плохой аргумент в арифметическом выражении.
{бадматч, V} Не удалось выполнить оценку выражения соответствия. Значение V не совпало.
function_clause При оценке вызова функции не найдено подходящего предложения функции.
{case_clause, V} При оценке выражения case не найдено соответствующей ветви. Значение V не совпало.
если да При вычислении выражения if истинная ветвь не обнаружена.
{try_clause, V} Соответствующая ветвь не найдена при вычислении of-section выражения try. Значение V не совпало.
undef Функция не может быть найдена при оценке вызова функции.
{badfun, F} Что-то не так с весельем F
{badarity, F} Забава применяется к неправильному количеству аргументов. F описывает развлечения и аргументы.
timeout_value Значение тайм-аута в выражении receive..after оценивается не как целое число или бесконечность.
noproc Попытка установить ссылку на несуществующий процесс.

Ниже приведен пример того, как можно использовать эти исключения и как это делается.

  • Первая функция генерирует все возможные типы исключения.

  • Затем мы пишем функцию-оболочку для вызова generate_exception в выражении «попробуй ... поймай».

пример

-module(helloworld). 
-compile(export_all). 

generate_exception(1) -> a; 
generate_exception(2) -> throw(a); 
generate_exception(3) -> exit(a); 
generate_exception(4) -> {'EXIT', a}; 
generate_exception(5) -> erlang:error(a). 

demo1() -> 
   [catcher(I) || I <- [1,2,3,4,5]]. 
catcher(N) -> 
   try generate_exception(N) of 
      Val -> {N, normal, Val} 
   catch 
      throw:X -> {N, caught, thrown, X}; 
      exit:X -> {N, caught, exited, X}; 
      error:X -> {N, caught, error, X} 
   end. 
      
demo2() -> 
   [{I, (catch generate_exception(I))} || I <- [1,2,3,4,5]]. 
demo3() -> 
   try generate_exception(5) 
   catch 
      error:X -> 
         {X, erlang:get_stacktrace()} 
   end. 
   
lookup(N) -> 
   case(N) of 
      1 -> {'EXIT', a}; 
      2 -> exit(a) 
   end.

Если мы запустим программу как helloworld: demo (). , мы получим следующий результат -

Вывод

[{1,normal,a},
{2,caught,thrown,a},
{3,caught,exited,a},
{4,normal,{'EXIT',a}},
{5,caught,error,a}]