Комментарии 18
Снижение производительности - вероятно, во всех других случаях обработки Result мы никогда не выполняем проверку на Ok или Err (то есть это замечание - явная ложь).
Непредсказуемое поведение - не могу придумать ни одного примера.
Отчего это читабельность кода снизится? Я вот совсем не вижу этого снижения.
Паника - не трудноотслеживаемая ошибка ни разу. И ошибки она никак не маскирует. В общем вся статья - ошибка от начала и до конца. Единственно, желательно вместо unwrap использовать expect - тогда сообщение паники можно сделать более содержательным.
В целом я согласен с комментарием, в тексте действительно много мусора.
Но в первом случае (про перформанс) автор всё-таки, вероятно, прав.
for _ in 1..1001 {
do_something(maybe_int.unwrap());
}
делает unwrap 1000 раз, а
if let Some(int) = maybe_int {
for _ in 1..10001 {
do_something(int);
}
}
всего один
Ну так ведь это не эквивалентное сравнение. Можно же сделать
let int = maybe_int.unwrap();
for _ in 1..1001 {
do_something(int);
}
Да, конечно.
Общая рекомендация "делайте проверку на err в коде один раз на переменную" (что дословно написано в тексте), или, даже, "парсите, а не валидируйте" - выглядит верной в общем случае (не смотря на то, что остальные тезисы в статье откровенно слабые).
Этоивсе сведется к одному и тому же ассемблеру, так что не принципиально. Компилятор все оптимизирует
Т.е. если Вы анврапаете результат получения данных с базы и она легла - то не будет проблем? А если файл вдруг не читается из-за лока другим процесом? Примеров можно привести кучу.
Главное правило для использования unwrap
против expect
заключается в том, что unwrap
должен использоваться только в том случае, если программа гарантирует отсутствие в этом месте отрицательного значения, поэтому паника никогда не произойдёт. Можно ещё в комментарии .unwrap(/* ... */)
написать явно, почему тут не будет паники.
...зачем писать комментарий, если можно написать его в .expect("текст объясняющий почему паника здесь не произойдет")
?
Можно. Но как тогда вы отличите те места, где паника потенциально может произойти от тех, где она произойти никак не должна? Придётся вчитываться во все тексты сообщений. А unwrap - сразу видно.
В чём разница
let filename = args.get(1).unwrap(/* отсутствует обязательный параметр */);
let filename = args.get(1).expect("отсутствует обязательный параметр");
В ожиданиях. Второй - это место с ожидаемым падением (если входные данные не корректны).
А unwrap предлагается использовать в каких-то таких случаях:
if (args.len() == 2 || args.len() == 5) {
let filename = args.get(1).unwrap(/*just checked len > 1*/)
<...>
}
Конкретно у get есть версия, которая просто паникует (get_unchecked), но такой аналог есть не у всех функций возвращающих option.
Конкретно у get есть версия, которая просто паникует
Не паникует, а предполагает, что программист только что всё проверил другими способами (как следствие - требует unsafe в качестве подтверждения).
Так expect-то он тоже не для повседневного использования. По-хорошему, expect тоже нельзя использовать если есть альтернативы, а только там где он никогда не должен вызваться в рантайме, т.к. в большинстве случаев программа не должна паниковать, а должна пузырьковать ошибку обратно в main() и там грациозно завершаться с ошибочным exit code.
Для ситуаций, когда ошибки гарантировано не будет, существует unwrap_unchecked
, unwrap
и expect
же для тех ситуаций, в которых программа при ошибке вообще не сможет корректно работать.
будет паника, которая может закрашить всю программу. Это не только ужасно с точки зрения пользователя, но также не помогает в понимании и отладке прпроблемы.
Для пользователя может и да, но найти причину такого краша с RUST_BACKTRACE=1 секундное дело. И конечно же grep unsafe|unwrap|except
это может маскировать ошибки, скрывать баги, делать ваш код менее читабельным, приводить к непредсказуемому поведению и снижению производительности
Маскировать ошибки и баги? Вы о чём? Объясните пожалуйста как паника "скрывает" баги? Что непредсказуемого в панике? Почему снижается производитель? (пример с unwrap() в hot loop не берём)
Ошибки нужно обрабатывать, это верно, но то что вы написали в статье не соответствует действительности.
А ведь эти же люди будут учить кого-то расту.
Интересно, на самом деле, посмотреть на примеры кода, а не на абстрактное "не используйте unwrap". Показали бы пример с unwrap, а потом то, как его избежать.
В целом с общим посылом статьи я полностью согласен: не используйте unwrap, потому как есть более содержательный expect. В эту функцию принято передавать сообщение об ожидаемом поведении, чтобы если вдруг возникнет паника, можно было бы быстро понять в чём проблема.
Избегать unwrap/expect мало смысла. Если вы пишете хоть сколько-то полезный код, в нём всё равно есть много операций, которые паникуют (скажем, деление на 0 или обращение по несуществующиму ключу в хешмау через [] оператор). Если код паникует, то это считается ошибкой программиста. Но это не значит, что ошибка в том, что программист написал unwrap, скорее в том, что он нарушил инвариант программы и ему стоит исправить код. unwrap/expect это полезные функции, так как позволяют понять где возникла ошибка, чтобы потом её исправить. Если в вашем коде нарушена логика работы, то прятать её под ковёр, вместо того, чтобы как можно скорее сообщить об ошибке - только сделает систему менее предсказуемой и менее надёжной.
Не следует путать ошибку программиста и штатное возвращение Result::Err
Единственный случай, когда избегать любую панику полезно, если вам действительно требуется полностью надёжная система, которая никогда не упадёт. В таком случае при возникновении бага лучше будет вернуть Result::Err
но это редкий случай относительно обычного прикладного кода. Даже при использовании раста в ffi, вместо избегания паники лучше её перехватывать.
В целом, любая "обработка ошибок" должна быть разумна. Раст не просто так предоставляет функционал паники. Конечно, если возможно какие-то разумно обработать Err или None, то это нужно сделать. Но паника при получении некорректного результата, это тоже обработка ошибок. Если в программе произошло то, что не должно было произойти, паника - это самый разумный выбор
Rust: ни в коем случае не используйте unwrap() в продакшене