Alternatives for unwrapping Option<T>

I am thinking about the case where I have an Option, and I only need to do something in the Some(thing) case. I have used "if let Some(x) = optionvalue {...}; I was reading something else, and realized I could use optionvalue.map({|x| ...}). Is there a reason to prefer one or there other?
Thank you,
Joel

Use map() if you need an output Option produced, and if let if you don't.

Reasons:

  • You can use control flow like break, return, ?, or await inside of an if let just like an if; you can’t do the same things with map() since the closure is a different function.
  • map() is extra work for the compiler, without any benefit in this case, since it has to process a closure construction and a generic function call; if let is simple nearly-primitive control flow.
  • It's not idiomatic to use map() when its result is ignored.
4 Likes

Thanks. That is an understandable balance. I will have to look at my various uses.

Do check out the various methods available, though: for example inspect is a closer match to your intention, and is often handy when you're "chaining" methods already.

Sometimes there's methods that are pretty ugly to implement yourself (without unsafe) like take_if where the borrow checker isn't (yet!) smart enough to see what you're doing with matching.

1 Like

You can also use let Some(...) else if you e.g. want to early return in the None case:

fn selection_sort<T>(lst: &mut [T])
where
    T: Ord,
{
    let Some(max_idx) = lst.len().checked_sub(1) else {
        return;
    };

    for i in 0..max_idx {
        let mut min = i;

        for j in (i + 1)..=max_idx {
            if lst[j] < lst[min] {
                min = j;
            }
        }

        lst.swap(min, i);
    }
}
3 Likes