Усі помилки в Elixir реалізують Exception Behaviour. Так само, як і Access Behaviour, Exception Behaviour визначає функції зворотного виклику, які модуль має реалізувати, щоб виконати програмний контракт цієї поведінки. Щойно помилку визначено, вона має такі властивості:
:message.raise/1 і raise/2, щоб згенерувати потрібну помилку.Exception Behaviour також визначає дві функції зворотного виклику: message/1 та exception/1. Якщо їх не реалізовано, використовуються типові реалізації. message/1 перетворює структуру помилки на читабельне повідомлення, коли його викликають через raise. exception/1 дає змогу додати до повідомлення додатковий контекст, коли його викликають через raise/2.
Щоб визначити виняток на основі модуля помилки, скористаймося макросом defexception:
# Defines a minimal error, with the name `MyError`
defmodule MyError do
defexception message: "error"
end
# Defines an error with a customized exception/1 function
defmodule MyCustomizedError do
defexception message: "custom error"
@impl true
def exception(value) do
case value do
[] ->
%MyCustomizedError{}
_ ->
%MyCustomizedError{message: "Alert: " <> value}
end
end
end
Визначені помилки можна використовувати так само, як вбудовану помилку, за допомогою raise/1 або raise/2.
raise/1 генерує конкретну помилку за назвою її модуля, а якщо аргумент є рядком тексту (англ. string), буде згенеровано RuntimeError із цим рядком тексту як повідомленням.raise/2 генерує конкретну помилку за назвою її модуля та приймає аргумент з атрибутами, який використовується, щоб отримати помилку з відповідним повідомленням.Продовжуючи працювати в Instruments of Texas, ми бачимо поступ у роботі над реалізацією калькулятора зі зворотним польським записом на Elixir. Наша команда хотіла б мати змогу викликати помилки, конкретніші за загальні помилки зі стандартної бібліотеки. Ми ще дещо досліджуємо, але вже вирішили реалізувати дві нові помилки, які втілюють Exception Behaviour.
Ділення числа на нуль дає невизначений результат, і команда вирішує, що найкраще подати його як помилку.
Реалізуйте модуль DivisionByZeroError з таким повідомленням про помилку: "division by zero occurred"
raise DivisionByZeroError
# => ** (DivisionByZeroError) division by zero occurred
Калькулятори зі зворотним польським записом використовують стек, щоб зберігати числа до того, як їх додадуть. Команда подає цей стек як список чисел (цілих і з плаваючою комою), наприклад: [3, 4.0]. Кожній операції потрібна певна кількість чисел у стеку, щоб виконати своє обчислення. Коли чисел у стеку не вистачає, це називається помилкою спустошення стека. Реалізуйте виняток StackUnderflowError, який надає типове повідомлення та необовʼязковий додатковий контекст
raise StackUnderflowError
# => ** (StackUnderflowError) stack underflow occurred
raise StackUnderflowError, "when dividing"
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
Реалізуйте функцію divide/1, яка приймає стек (список із двох чисел) і:
RPNCalculator.Exception.divide([])
# => ** (StackUnderflowError) stack underflow occurred, context: when dividing
RPNCalculator.Exception.divide([0, 100])
# => ** (DivisionByZeroError) division by zero occurred
RPNCalculator.Exception.divide([4, 16])
# => 4
Зверніть увагу, що порядок елементів у списку зворотний!
Зареєструйтеся на Exercism, щоб вивчати й опановувати Elixir, а також 58 концепцій168 вправ та справжнє наставництво від людей, і все це безкоштовно.