Pull to refresh

Comments 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 - сразу видно.

Не понимаю, почему unwrap «сразу видно», а expect — нет?
В чём разница
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.

Да, теперь понял. В тех местах, где программист уверен, предпочтительнее unwrap, потому что непонятно, что писать в сообщении.

Конкретно у get есть версия, которая просто паникует

Не паникует, а предполагает, что программист только что всё проверил другими способами (как следствие - требует unsafe в качестве подтверждения).

Так expect-то он тоже не для повседневного использования. По-хорошему, expect тоже нельзя использовать если есть альтернативы, а только там где он никогда не должен вызваться в рантайме, т.к. в большинстве случаев программа не должна паниковать, а должна пузырьковать ошибку обратно в main() и там грациозно завершаться с ошибочным exit code.

Для ситуаций, когда ошибки гарантировано не будет, существует unwrap_unchecked, unwrap и expect же для тех ситуаций, в которых программа при ошибке вообще не сможет корректно работать.

Для ситуаций, когда ошибки гарантировано не будет, существует unwrap_unchecked

Сегодня гарантии, а завтра UB

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

Для пользователя может и да, но найти причину такого краша с 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, то это нужно сделать. Но паника при получении некорректного результата, это тоже обработка ошибок. Если в программе произошло то, что не должно было произойти, паника - это самый разумный выбор

Sign up to leave a comment.