How to log error and return/continue a result/option

Viewed 95

I have come across many instances in that I need to write a code similar to this snippet. I was wondering if there's a shorter way to do it?

loop {
    let res = match do() {
        Ok(res) => res,
        Err(e) => {
            eprintln!("Error: {}", e);
            continue;
        }
    }
        
    // Do stuff with `res` ...
}

or

fn some_fn() {
    let res = match do() {
        Some(res) => res,
        None => {
            eprintln!("Error: not found");
            return;
        }
    }
        
    // Do stuff with `res` ...
}

I was looking for something like the ? keyword to return early with errors but in a case where the function returns nothing and I just want to return nothing if the result is None/Error.

Maybe something like this:

loop {
    do().unwrap_or_log(|e| eprintln("{}", e).continue // :D
}

And consider do() is never gonna be this short. It's probably a chain of a few function calls which is already too long.

Maybe the way I'm doing it is the only way or maybe I'm doing something wrong which makes to do this and I shouldn't be doing it!?

1 Answers

This is pretty much how it is. However nice the many chaining functions are, they cannot affect the control flow where they are used.

One suggestion I may make: if you have many fallible operations that need to be logged and continued in an infallible context, you could move those into a single fallible function that you then can log and skip any errors all at once.


You aren't the only person to have complaints though and others have suggested changes to make this flow less bothersome.

There's the let else proposal, which I believe is implemented in the nightly compiler. It just needs to be documented and stabilized. It would look like this (playground):

let Ok(res) = do_this() else { continue };

Or perhaps a postfix macro proposal could be implemented eventually, which may look like this:

let res = do_this().unwrap_or!{ continue };

I'll note though that neither of these give access to the Err(e) value. So you'd still need a custom method for logging.

Related