Rust:从标准输入读取和映射行并处理不同的错误类型
Posted
技术标签:
【中文标题】Rust:从标准输入读取和映射行并处理不同的错误类型【英文标题】:Rust: Read and map lines from stdin and handling different error types 【发布时间】:2020-03-29 22:05:05 【问题描述】:我正在学习 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 后立即丢弃它。
我想我需要创建某种 Enum 类型来保存各种可能的错误,可能是这样的:
#[derive(Debug)]
enum InputError
Io(std::io::Error),
Parse(std::num::ParseIntError),
但是,我不太明白如何将所有内容放在一起以使其干净,并避免在任何地方显式匹配和强制转换。另外,是否有某种方法可以自动创建这些枚举错误类型,或者我每次执行此操作时都必须明确枚举它们?
【问题讨论】:
【参考方案1】:你在正确的轨道上。
我解决这个问题的方法是使用您定义的枚举,
然后为您感兴趣的错误类型添加From
的实现。
这将允许您在地图上使用 ?
运算符来获得所需的行为。
#[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
这样的错误处理板条箱来进一步减少一些错误样板,但在这种情况下并不算多。
【讨论】:
作为替代方案,您可以通过将my_values
声明为Result<Vec<u32>,Box<dyn Error>>
类型来避免编写From
实现,因为?
自动框错误。另见:***.com/questions/48430836/…
@asky 是的,这也可以。但我认为,如果您想稍后进行任何更高级的错误处理,那么恢复原始错误的具体类型可能会很棘手。 (这可能是为什么有这么多错误处理板条箱的重要部分)。以上是关于Rust:从标准输入读取和映射行并处理不同的错误类型的主要内容,如果未能解决你的问题,请参考以下文章