Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the idiomatic way of using an if-let binding when matching a `Result` and still being able to capture the error?

Tags:

rust

fn lines_from_file<F>(filename: F) -> Result<io::Lines<BufReader<File>>, io::Error>
where
    F: std::convert::AsRef<std::path::Path>,
{
    let file = File::open(filename)?;
    Ok(io::BufReader::new(file).lines())
}

fn main() {
    let filename: &str = "input.pdl";
    // This works fine
    match lines_from_file(filename) {
        Ok(lines) => {
            for line in lines {
                println!("{:?}", line);
            },
        }
        Err(e) => println!("Error {:?}", e),
    }
}

I'd like to use this instead:

if let lines = Ok(lines_from_file(filename)) {
    for line in lines {
        println!("{:?}", line);
    }
} else {
    println!("Error {:?}" /*what goes here?*/,)
}

But that gives an error:

| if let lines = Ok(lines_from_file(filename)) {
|                ^^ cannot infer type for `E`

What is the idiomatic way of using an if-let binding when matching a Result and still being able to capture the error?

like image 245
Delta_Fore Avatar asked Nov 12 '17 12:11

Delta_Fore


People also ask

What is if let in Rust?

The if let expression in rust allows you to match an expression to a specific pattern. This is different from the if expression that runs when a condition is true. Using the let keyword, you can specify a pattern that is compared against the specified expression.

What does OK () do in Rust?

It is an enum with the variants, Ok(T) , representing success and containing a value, and Err(E) , representing error and containing an error value. Functions return Result whenever errors are expected and recoverable.

How do you unwrap in Rust?

To “unwrap” something in Rust is to say, “Give me the result of the computation, and if there was an error, panic and stop the program.” It would be better if we showed the code for unwrapping because it is so simple, but to do that, we will first need to explore the Option and Result types.


1 Answers

[...] using an if-let binding when matching a Result and still being able to capture the error?

This is fundamentally impossible with one if let. The if let construct's only purpose is to make life easier in the case where you only want to destructure one pattern. If you want to destructure both cases of a Result, you have to use match (or multiple if let or unwrap(), but this is not a good solution). Why you don't want to use match in the first place?

Regarding your compiler error: you added the Ok() on the wrong side:

if let Ok(lines) = lines_from_file(filename) { ... }

This is the correct way of using if let: the destructuring pattern to the left, the expression producing a value to the right.

like image 144
Lukas Kalbertodt Avatar answered Sep 22 '22 04:09

Lukas Kalbertodt