Reputation: 16015
I'm in progress of learning Rust and I'm trying to apply similar style I'm using with C++. With C++ I would be using RAII and exceptions and the closest I can get with Rust is RAII combined with early return with error Result. As such, when I write code such as
fn parse_meminfo() -> Result<Meminfo, io::Error> {
// ...
let file = File::open("/proc/meminfo")?;
for line in io::BufReader::new(file).lines() {
let line = line?;
// ...
Is it possible to somehow avoid the fragment let line = line?;
of code? I already tried
for line in io::BufReader::new(file).lines()?
and
for line? in io::BufReader::new(file).lines()
and
for Ok(line) in io::BufReader::new(file).lines()
and
for line in io::BufReader::new(file).lines().expect("failed to read line")
but rustc
wasn't happy with any of those. First and fourth have the test in logically wrong position because ?
and expect()
are testing the iterator instead of the item, if I've understood correctly. Second was syntax error, and the syntax Ok(line)
is not happy to ignore the error because that doesn't mean early return. I would like to have early return with the error if the iterator in the loop gives an error and adding one extra line of code just for that seems silly and that test seems a bit detached from the actual loop. Can you suggest anything better? If the let line = line?;
is indeed the idiomatic style, then I guess I would have to learn to love it.
Upvotes: 0
Views: 1425
Reputation: 42472
Is it possible to somehow avoid the fragment let line = line?; of code?
Depending how you're using line
, you could just tack on the ?
over there. expr?
simply desugars to1
match expr {
Ok(v) => v,
Err(e) => return e.into()
}
So you can see how the second attempt would not work (the left hand side of the for...in
is an irrefutable pattern, not an expression).
The error handling here is largely orthogonal to the iteration, and iteration doesn't (at this juncture, though it seems unlikely that'll be added) have first-class support for error signaling, so you have an Iterator<Item=Result<...>>
and you handle the Result
however you wish.
If you don't care for the error reporting you could always .lines().map(|v| v.expect(...)
and that'll immediately panic at the first error, but I don't know that that's what you're looking for.
Upvotes: 2