Есть ли способ заставить expect () выводить более удобное сообщение?

Я считаю сообщение, созданное expect(), очень недружелюбным для пользователей. Рассмотрим следующий короткий пример ...

use std::env;

fn main() {
    let imagefn = env::args().skip(1).next().expect("Filename not provided.");
    println!("{}", imagefn);
}

Эти ошибки с:

thread 'main' panicked at 'Filename not provided.', libcore/option.rs:960:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Я считаю expect() очень полезным для написания быстрого кода, но хотел бы вывести что-то вроде этого:

Filename not provided.

Со всей остальной информацией скрытой, если я действительно не предоставлю переменную среды, о которой я, как разработчик, должен знать. Думаю, мои вопросы:

  1. Есть ли способ переопределить expect() для этого?
  2. Почему expect() выводит недружественное сообщение даже в сборках релизов?
Вопросы, просящие нас порекомендовать или найти книгу, инструмент, библиотеку программного обеспечения, учебное пособие или другой внешний ресурс, не относятся к теме Stack Overflow, поскольку они, как правило, привлекают самоуверенные ответы и спам. - Я удалил это из вашего в остальном хорошего вопроса.
Shepmaster 10.08.2018 15:44

В целом, я думаю, вы неправильно на это смотрите. expect следует использовать никогда для ошибок, которые пользователь может разумно увидеть или вызвать. Он предназначен для ошибок на уровне программиста. Все остальное должно обрабатываться вашей программой.

Shepmaster 10.08.2018 15:48

@Shepmaster Я понял. Я написал: «Я считаю, что expect () очень полезен для написания быстрого кода» ... вы правы, что настоящая обработка ошибок должна использоваться в нетривиальных сценариях.

Fredrick Brennan 10.08.2018 15:51
expect можно улучшить с помощью макроса, например crates.io/crates/unwrap.
ArtemGr 10.08.2018 16:17
3
4
454
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

expect() - это просто удобный условный вызов panic!():

pub fn expect(self, msg: &str) -> T {
    match self {
        Some(val) => val,
        None => expect_failed(msg) // expect_failed calls panic!()
    }
}

В идеале вы, вероятно, должны справиться с этим с помощью оператора ? внутри функции, возвращающей Option или Result, чтобы иметь возможность обрабатывать такого рода проблемы более изящным образом.

Если вы просто хотите вернуть более понятное сообщение и выйти, вы можете реализовать свою собственную функцию, печатающую сообщение и завершающуюся с помощью процесс :: выход.

Ответ принят как подходящий

Вы можете использовать set_hook для изменения сообщения о панике. Пример:

use std::panic::set_hook;

fn main() {
    set_hook(Box::new(|info| {
        if let Some(s) = info.payload().downcast_ref::<String>() {
            println!("{}", s);
        }
    }));

    // Displays: "My error message":
    Option::None::<i32>.expect("My error message");
}

Вы также можете использовать message(), который попроще, но нестабилен (пока):

#![feature(panic_info_message)]

use std::panic::set_hook;

fn main() {
    set_hook(Box::new(|info| {
        println!("{:?}", info.message().unwrap());
    }));

    Option::None::<i32>.expect("My error message");
}

Обратите внимание, что вы можете создать свой собственный метод расширения, который вызывает панику с пользовательским типом. В ловушке паники, если вы можете перейти к своему индивидуальному типу, вы уверены в происхождении паники.

Другие вопросы по теме