rust - 如何模仿效用函数的可变参数?

标签 rust

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 还不支持可变参数,所以我必须这样使用它,对吗?

something().or_exit(&format!("Ah-ha! An error! {}", "blah"));

与 Java、Kotlin 或 C 相比,这太冗长了。解决这个问题的首选方法是什么?

最佳答案

我不认为您建议的 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");
}

Rust Playground

请注意,如果用户提供无效参数,这可能不会产生最好的错误消息,我不想对您的代码进行太多更改,但是如果您决定实际上只使用糖而不是其他任何东西,您可能应该扩展您的 API采用闭包而不是字符串。您可能还想重新考虑宏的命名。

关于rust - 如何模仿效用函数的可变参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49759470/

相关文章:

vector - 不重新借用可变切片时在 for 循环中移动错误

linux - 在 Mac OSX 上交叉编译到 x86_64-unknown-linux-gnu 失败

types - 为什么 Rust 中没有任意大小的二进制整数类型?

rust - "unresolved import -- maybe a missing extern"extern声明存在时

rust - 在 Rust 中创建带有结构的 hashmap

arrays - 如何在 Rust 中交换多维数组的值?

rust - 用 0 向左填充字符串的最简单方法是什么?

rust - 为什么在不同的 mod 中找不到我的 const 变量

vector - 从旧 Vector 创建新 Vector?

rust - 将 Diesel 连接注入(inject) Iron 中间件