Обработайте неверную длительность занятия без остановки программы и проследите отложенное действие после каждой проверки. Затем вызовите ошибку доступа к массиву и исправьте индекс.
Сначала пройдите раздел Данные и управление. Используйте установленный Топаз и ту же рабочую папку.
Обработайте верный и неверный ввод
Сохраните код в файле failures-resources.tpz.
record УчебнаяЗадача {
название: string,
минуты: int,
}
function разобратьМинуты(текст: string) -> Result<int, string> {
match toInt(текст) {
case Some(значение) if значение > 0 => Ok(значение)
case _ => Err("minutes must be a positive integer")
}
}
function создатьЗадачу(название: string, текстМинут: string) -> Result<УчебнаяЗадача, string> {
let минуты = разобратьМинуты(текстМинут)?
Ok(УчебнаяЗадача { название: название, минуты: минуты })
}
function проверить(текстМинут: string) -> () {
print("input: {текстМинут}")
defer { print("inspection finished") }
match создатьЗадачу("Build application", текстМинут) {
case Ok(задача) => print("ready: {задача.название}, {задача.минуты} minutes")
case Err(сообщение) => print("cannot add task: {сообщение}")
}
}
проверить("25")
проверить("later")В той же папке проверьте и запустите файл.
topaz check failures-resources.tpz
topaz run failures-resources.tpzОбе команды завершаются с кодом 0. Программа сообщает о неверном вводе и продолжает работу.
input: 25
ready: Build application, 25 minutes
inspection finished
input: later
cannot add task: minutes must be a positive integer
inspection finishedПроследите ввод через Option и Result
Option представляет значение, которое может отсутствовать. Вызов toInt("25") возвращает Some(25). Вызов toInt("later") возвращает None, поскольку текст нельзя разобрать как целое число.
Result содержит либо успешное значение в Ok, либо значение ошибки в Err. Функция разобратьМинуты возвращает Ok(значение), когда полученное число удовлетворяет условию значение > 0. При отсутствии числа, нуле или отрицательном числе она возвращает Err с объяснением.
В функции создатьЗадачу знак ? после разобратьМинуты(текстМинут) извлекает целое число из Ok. При получении Err он сразу возвращает эту ошибку из создатьЗадачу. Задача в таком случае не создаётся. Это возможно, поскольку обе функции возвращают совместимый Result со строкой ошибки.
Функция проверить разбирает результат через match и выводит новую задачу или сообщение об ошибке.
Выполните действие при завершении функции
defer регистрирует действие для выхода из окружающей области видимости. Здесь это тело функции проверить. Поэтому строка inspection finished появляется после каждой проверки. Сообщение для "later" тоже является обычным результатом, который программа обрабатывает.
Используйте defer для очистки, например для закрытия открытого файла. Зарегистрированная очистка выполняется и при выходе из области через return или ?. Ошибка выполнения, называемая fault, немедленно останавливает вычисление, а очистка после этого не определена. Представляйте ожидаемые ошибки ввода через Result, чтобы программа могла завершить обычную очистку.
Найдите и исправьте неверный индекс
Сохраните эту программу в отдельном файле intentional-fault.tpz.
let задачи = ["Run first program", "Build application"]
print(задачи[2])Выполните topaz run intentional-fault.tpz. Команда завершается с ненулевым кодом и указывает место неверного обращения.
error[TPZ4001]: index 2 is out of bounds for an array of length 2
--> intentional-fault.tpz:2:7
|
2 | print(задачи[2])
| ^^^^^^^^^
Два элемента имеют индексы 0 и 1. Индекс 2 запрашивает несуществующий элемент и вызывает ошибку выполнения, которая останавливает вычисление. Значение Err для обработки через match или ? не возвращается.
В строке 2 замените задачи[2] на задачи[1] и снова запустите файл. Он выведет Build application и завершится с кодом 0.
Выберите обработку отсутствующего или неверного значения
| Ситуация | Что использовать или сделать |
|---|---|
| Значение может отсутствовать | Option с Some(значение) или None |
| Вызывающему коду нужен результат или объяснение ошибки | Result с Ok(значение) или Err(ошибка) |
| Функция должна передать ошибку вызывающему коду | ? внутри функции с совместимым типом результата |
| Неверная операция вызывает ошибку выполнения | Исправить операцию или проверить данные перед её выполнением |
| Область видимости отвечает за очистку | Зарегистрировать действие через defer |
Попробуйте
Добавьте проверить("0") в конец failures-resources.tpz. Предскажите дополнительные строки, затем проверьте и запустите файл.
Показать ответ
Сначала появится input: 0. Ноль не удовлетворяет условию значение > 0, поэтому следующей строкой будет cannot add task: minutes must be a positive integer. Последней появится inspection finished, поскольку выполнение штатно выходит из области видимости проверить.
Переходите к следующему занятию
Можно продолжать, когда вы проследили путь "later" от None до Err и нашли место возврата ошибки через ?. Убедитесь, что добавленный нулевой ввод выводит ошибку и строку очистки, а исправленное обращение к массиву работает.
Перейдите к разделу Первое приложение, чтобы разделить планировщик занятий на два файла. Подробные правила описаны в разделах Null, Option, Result и ошибки и Defer и ресурсы.