error-handling - Rust:从标准输入读取和映射行并处理不同的错误类型

标签 error-handling rust idioms

我正在学习 Rust 并尝试用它解决一些基本的算法问题。在许多情况下,我想从标准输入读取行,对每行执行一些转换并返回结果项的向量。我这样做的一种方法是这样的:

    // Fully working Rust code
    let my_values: Vec<u32> = stdin
        .lock()
        .lines()
        .filter_map(Result::ok)
        .map(|line| line.parse::<u32>())
        .filter_map(Result::ok)
        .map(|x|x*2) // For example
        .collect();

这可行,但当然会默默地忽略可能发生的任何错误。现在我想做的是:

    // Pseudo-ish code
    let my_values: Result<Vec<u32>, X> = stdin
        .lock()
        .lines() // Can cause std::io::Error
        .map(|line| line.parse::<u32>()) // Can cause std::num::ParseIntError
        .map(|x| x*2)
        .collect();

其中 X 是某种错误类型,我可以在之后进行匹配。最好我想一次一行执行整个操作,并在解析为 int 后立即丢弃字符串数据。

我认为我需要创建某种枚举类型来保存各种可能的错误,可能如下所示:

#[derive(Debug)]
enum InputError {
    Io(std::io::Error),
    Parse(std::num::ParseIntError),
}

但是,我不太明白如何将所有内容放在一起以使其干净并避免必须在各处显式匹配和强制转换。另外,是否有某种方法可以自动创建这些枚举错误类型,或者我每次执行此操作时都必须明确枚举它们?

最佳答案

你走在正确的道路上。 我解决这个问题的方法是使用您定义的枚举, 然后为您感兴趣的错误类型添加 From 的实现。 这将允许您在 map 上使用 ? 运算符来获得您想要的行为。

#[derive(Debug)]
enum MyError {
    IOError(std::io::Error),
    ParseIntError(std::num::ParseIntError),
}

impl From<std::io::Error> for MyError {
    fn from(e:std::io::Error) -> MyError {
        return MyError::IOError(e)
    }
}

impl From<std::num::ParseIntError> for MyError {
    fn from(e:std::num::ParseIntError) -> MyError {
        return MyError::ParseIntError(e)
    }
}

然后您可以将实际的转换实现为

let my_values: Vec<_> = stdin
    .lock()
    .lines()
    .map(|line| -> Result<u32,MyError> { Ok(line?.parse::<u32>()?*2) } )
    .collect();

这将为每个输入提供一个条目,例如:{Ok(x), Err(MyError(x)), Ok(x)}。 或者你可以这样做:

let my_values: Result<Vec<_>,MyError> = stdin
    .lock()
    .lines()
    .map(|line| -> Result<u32,MyError> { Ok(line?.parse::<u32>()?*2) } )
    .collect();

这将为您提供 Err(MyError(...))Ok([1,2,3])

请注意,您可以通过使用像 snafu 这样的错误处理包来进一步减少一些错误样板,但在本例中并不算太多。

关于error-handling - Rust:从标准输入读取和映射行并处理不同的错误类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59187274/

相关文章:

rust - 如何处理unwrap_or_else中的异常(Err)?

vector - 如何根据 Vector 中某个项目的信息修改 Vector?

memory - Clojure 惯用的内存高效循环

python - 如果函数有效则为真,如果函数出错则为假

c++ - 捕获不使用 try/catch 抛出的异常

swift - “ fatal error :在展开可选值时意外发现nil”是什么意思?

ios - Xcode应用程序崩溃且没有错误

rust - 如何从同一类型的另一个方法内部调用带有 &mut self 的方法?

f# - 可选地获取序列中的第一项

c++ - 使用数据库模型(键)来引用运行时对象,好主意还是坏主意?