How to deal with Result as a return type

So, yesterday I've learned that in order to avoid multiple calls to unwrap, one should instead return Result/Option. So having that in mind, what to do with the return type, in a sense, I have to unwrap it anyway? Do I?
Thanks in advance

Most programs will propapage all errors with ?, and then at the top level (usually the main function) have code like:

if let Err(e) = run_actual_program() {
    eprintln!("Failed to run program: {}", e);
    std::process::exit(1);
}

The main function itself can also return a Result, in which case errors will be debug-formatted to the standard error and the program will exit with 1.

One more question, how to handle non error? That is, how to handle the Result with no error. What I mean is, how to deal both with situation where there may be and error and situation where everything went fine?

There is no real strict rule about this.
you need to think about what the Err/None case means for you. If you need to ignore those you can do
if let Ok()/Some()

if you need to handle the error cases you can add the else block or a match statement

if you have some default value to use in case of a failure, use the unwrap_or() and unwrap_or_else() functions.

if you have no way to recover from the error feel free to panic

otherwise use ? to propagate it up to a reasonable place to do all those same things mentioned above. where you handle it is upto you to decide, you don't have to send it all the way up to main

as for returning results you might run into issues deciding what type the E in Result<T, E> should be, as different things will give you different errors

check out the anyhow crate for that. The idea is any Error that implements the Error trait can be converted into an anyhow::Error. So if a function returns Result<T, anyhow::Error> you can use ? on any type of Error and it'll be converted into an anyhow::Error

you can also use ok_or() and ok_or_else() to convert options into results then use ? on them

Thanks for the reply.
Imagine, I call a function:

if let Err(e) = do_something()
{
}
else
{
//how to get here the result of do_something?
}

use a match in that case

match do_something(){
     Ok(foo) =>{   
          // use foo here
     }
     Err(err) => {
          // use error here
     }
}

you can use else if Ok(foo) too if you want... but it's recommended to use match for exhaustive cases

1 Like

Thanks

Also, it's worth mentioning the ? operator.

match do_something() {
    Ok(val) => val,
    Err(e) => return Err(e),
}

Is equivalent to

do_something()?

In general if you're propagating an error it's always recommended to use the ? operator instead of manually using match.

2 Likes