Error propagation for if else statement

Hello,
I am somewhat new to Rust, and I start using the ? error propagation which is so great at making code more concise !

I have a frequent pattern in my code, and I wonder if there is a better way to do:
I check a condition, then in the if branch I return Some(x) or Result(x) according to the return type of the function, and in the else branch I return None or Err.

Here is a code sample (not the actual code):

fn optest(n: i32) -> Option<i32> {
    if n > 0 {
        Some(n)
    } else {
        None
    }
}

Is there a way to be more concise to express that ?

There's a boolinator crate, but I'm not at all sure using it is any clearer than if cond { Some(expr) } else { None }. I'd probably just leave the code as is, there's nothing ugly or unnecessarily verbose about it.

I wonder why you want to turn something short, sweet and obvious into something more "concise" that like would not be so clear.

I might be tempted to forget the "else" clause though:

fn optest(n: i32) -> Option<i32> {
    if n > 0 {
        return Some(n);
    }
    None
}
2 Likes

Well, it's not always as short and simple than in this example. And the case I'm most interested in is when the if/else is used as a statement. In this case, you can't dismiss the else clause or you will get a "mismatched types" error.

Anyway I will keep it like that, but I was hoping for something similar to this case : here, the 3rd snippet is much more "sweet" than the first 2.

// N°1
match plop(){
    Some(n) => {
        //complicated stuff with n
      Some("my precious")
    },
    None => None
}
// N°2
if let Some(n) = plop(){
    //complicated stuff with n
   Some("my precious")
} else {
    None
}
// N°3
let n = plop()?;
//complicated stuff with n
Some("my precious")

Thank you all for your answers.

@H2CO3 I just understood what you mean with the boolinator crate after writing my other examples. Thank you, I will look at it and see if this can make things clearer, or if it will just confuse everything.

That just looks like Option::map.

Using filter would be like this:

Some(n).filter(|&n| n > 0)

I don't know what you think, it's shorter but not really less complex.

In Nightly Rust you can use the experimental bool::then method:

fn optest(n: i32) -> Option<i32> {
    (n > 0).then(n)
}

(playground)

2 Likes

Oh that's a cool method !

I will stick to the if/else in my case, but thank you all for your answers, I learned some cool stuff!