Result.expect()
的控制台输出不是我需要的,所以我使用自己的版本扩展了Result
:
trait ResultExt<T> {
fn or_exit(self, message: &str) -> T;
}
impl<T> ResultExt<T> for ::std::result::Result<T, Error> {
fn or_exit(self, message: &str) -> T {
if self.is_err() {
io::stderr().write(format!("FATAL: {} ({})\n", message, self.err().unwrap()).as_bytes()).unwrap();
process::exit(1);
}
return self.unwrap();
}
}
据我所知,Rust还没有支持varargs,所以我必须这样使用它,对吗?
something().or_exit(&format!("Ah-ha! An error! {}", "blah"));
与Java,Kotlin或C相比,它过于冗长。解决这个问题的首选方法是什么?
答案 0 :(得分:3)
我不认为您建议的API特别符合人体工程学。如果最大性能很重要,将错误生成放在闭包中或为此提供API可能是有意义的,因此String
仅在实际存在错误时分配,这可能在某些事情发生时尤为重要。格式特别昂贵。 (与std::result::Result
的所有_else
方法一样。)
但是,您可以通过定义一个获取结果的宏,&str
和格式参数,使其更符合人体工程学。例如,这可能是这样的:(这是基于@ E_net4的评论)
macro_rules! or_exit {
($res:expr, $fmt:expr, $($arg:tt)+) => {
$res.unwrap_or_else(|e| {
let message = format!($fmt, $($arg)+);
eprintln!("FATAL: {} ({})\n", message, e);
process::exit(1)
})
};
}
fn main() {
let x: Result<i32, &'static str> = Err("dumb user, please replace");
let _ = or_exit!(x, "Ah-ha! An error! {}", "blahh");
}
请注意,如果用户提供无效参数,这可能不会产生最佳错误消息,我不想过多地更改您的代码,但是如果您决定实际上只使用宏而没有其他任何内容,那么您应该扩展您的API取一个闭包而不是一个字符串。您可能还需要重新考虑宏的命名。