I want to write something like this, but it won't compile due to a mismatch between types:
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let val = std::env::args()
.nth(1)
.ok_or("1 arg is expected")
.and_then(std::fs::File::open)
.and_then(serde_yaml::from_reader)?;
}
Because adding a map_err to every closure seems sluggish and 'boiler platy', I replace it with something like:
fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
let val = serde_yaml::from_reader(std::fs::File::open(
std::env::args().nth(1).ok_or("1 arg is expected")?,
)?)?;
}
The first one feels more natural and reads like English while the second feels sort of backwards.
Should I ditch the and_then and always use the ? operator?
If not, is there a way to make result combinator as smooth as the ? operator?
That’s a personal judgement and only you can answer it.
Frankly speaking no.
?performs conversions « implicitly » (not really implicitly since it’s very much part of its job, but the conversion doesn’t have to be invoked separately, maybe « tersely »?),and_thendoes not. That means when usingand_then, you have to perform these conversions yourself. That seems logical.You might be able to build a convenience macro for this tho. Or maybe add an extension method or wrapper type which can perform those conversions under the cover.