Menu
CoddyTech

Защищенные вызовы с pcall()

Часть раздела Логика и управление потоком путешествия по Lua на Coddy. Урок 33 из 54.

Хотя error() останавливает программу, когда что-то идет не так, иногда нужно обрабатывать ошибки, не допуская аварийного завершения. Функция pcall() в Lua позволяет безопасно выполнять код, который может завершиться с ошибкой.

Название pcall() означает «защищённый вызов». Оно оборачивает вызов функции в защитный слой, который перехватывает любые ошибки. Вместо того чтобы программа аварийно завершилась, pcall() возвращает информацию о том, что произошло.

Вот базовый синтаксис:

local status, result = pcall(functionName, arg1, arg2)

Функция pcall() возвращает два значения. Первое — логический статус: true, если функция выполнилась успешно, или false, если произошла ошибка. Второе значение зависит от статуса: при успешном выполнении это возвращаемое функцией значение; если произошла ошибка — сообщение об ошибке.

Вот практический пример:

function divide(a, b)
    if b == 0 then
        error("Cannot divide by zero")
    end
    return a / b
end
local success, result = pcall(divide, 10, 0)
if success then
    print("Result: " .. result)
else
    print("Error caught: " .. result)
end

В этом примере деление на ноль вызывает ошибку, но вместо аварийного завершения программы её перехватывает pcall(). Программа продолжает работу и может корректно обработать ошибку, проверив значение статуса.

Имей в виду, что pcall() перехватывает все ошибки внутри вызова, включая неожиданные ошибки в коде, и сообщает о них одинаково. Поэтому оборачивай только вызов, который может завершиться ошибкой, а для ожидаемых ошибок предпочитай функцию, которая возвращает nil и сообщение, как в предыдущем уроке.

challenge icon

Задание

Легко

Напиши функцию safeCalculate, которая принимает operation, a и b и возвращает результат вычисления или сообщение об ошибке.

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

Логика:

  • Создай внутреннюю функцию, которая проверяет тип операции и выполняет вычисление
  • Для "add" верни a + b
  • Для "subtract" верни a - b
  • Для "multiply" верни a * b
  • Для "divide" проверь, равен ли b 0, и вызови error("Division by zero", 0), если это так; в противном случае верни a / b
  • Для любой другой операции вызови error("Invalid operation", 0)
  • Используй pcall(), чтобы выполнить внутреннюю функцию
  • Если выполнение прошло успешно, верни "Result: ", за которым следует результат
  • Если произошла ошибка, верни "Error: ", за которым следует сообщение об ошибке

Передай 0 в качестве второго аргумента error(). Этот аргумент задаёт уровень ошибки, а 0 указывает Lua не добавлять имя файла и номер строки перед сообщением, поэтому возвращаемая строка будет точно равна "Error: Division by zero".

Параметры:

  • operation (строка): операция для выполнения ("add", "subtract", "multiply" или "divide")
  • a (число): первый операнд
  • b (число): второй операнд

Возвращаемое значение: строка, содержащая либо "Result: ", за которым следует результат вычисления, либо "Error: ", за которым следует сообщение об ошибке (строка)

Попробуйте сами

function safeCalculate(operation, a, b)
    -- Напишите код здесь
    -- Примечание: вызовите error(message, 0), чтобы Lua не добавлял имя файла и
    -- номер строки перед вашим сообщением.
end
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Логика и управление потоком

Потренируйтесь самостоятельно: Онлайн-компилятор Lua