Result : How to run command before returning an error


#1

If we use the ? at the end of the line, it returns the error if error happens. Is there a way to call one more function before returning the error ?

For now, I have to put the Result in a variable, call my function and just apply the “?” on my result to return if I got an error. Is there an easy way to do that ?


let result = my_call(param); // Return a result<(),error>
remove(param); // I can’t return without running this function, this is why I didn’t use ? before.
let _ = result?; // Just to return the error if I got an error on the call.

I don’t mind if my_call got and error or not, I want to call my function “remove” before returning the function. Is there an elegant way to do that ? Thx


#2

Scopeguard could make this nicer.

defer!({
    remove(param);
});
my_call(param)?;

#3

Result is an enum so you can just match the result. ? is syntactic sugar for the try! macro which is just a shortcut for matching on the enum (https://doc.rust-lang.org/book/first-edition/error-handling.html#the-try-macro)

match my_call(param) {
    Ok(x) => println!("{:?}", x),
    Err(e) => {
        remove(param);
    }
}

https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html


#4

I know that, but I wanted to run the extra function for both (error or not), not only if there is an error. So it would be this :

match my_call(param) {
Ok(x) => {
remove(param);
//Do more stuff here…
},
Err(e) => {
remove(param);
return Err(e.into());
}
}

I thought to be able to do it with function “and” “and_then”… on Result, but didn’t find a way to do it.


#5

I don’t think there’s anything for this in the standard library, BUT thanks to Rust’s traits it doesn’t have to be. You can add your own.

trait Anyway: Sized {
   fn anyway<F: FnOnce()>(self, callback: F) -> Self { callback(); self }
}
impl<T,E> Anyway for Result<T,E> {}

…
my_call(param).anyway(|| remove(param))?;

But your 3-line solution is OK IMHO:

let result = my_call(param); 
remove(param); 
let _ = result?;