103. bool::then_some — Turn a Condition Into an Option Without an if
Writing if condition { Some(value) } else { None } for the hundredth time? bool::then_some collapses that whole pattern into a single chainable call.
The familiar boilerplate
You have a bool and you want to lift it into an Option. The naive form works, but it’s noisy and breaks chains:
| |
Three lines and an if/else for what is conceptually “if true, wrap it.” It also doesn’t slot into iterator chains — you’d have to wrap it in a closure.
then_some: the eager form
bool::then_some(value) returns Some(value) if the bool is true, None otherwise:
| |
One line, no branches in sight. The intent reads exactly like the English: if even, then some n * 2.
then: the lazy form
then_some always evaluates its argument — fine for cheap values, wasteful for expensive ones. Use then(|| ...) when the value should only be computed when the condition holds:
| |
The parse only runs when the string is all digits. With then_some(s.parse().unwrap()) you’d unwrap on every call — instant panic on bad input.
Where it really shines: filter_map chains
The big payoff is in iterator pipelines. Filter and transform in one step, no closure-returning-Option boilerplate:
| |
Compare to the if/else version inside the closure — it works, but it’s twice as wide and the else None arm adds zero information.
Watch the eager trap
then_some evaluates its argument unconditionally — which means an “obvious” guard like this is actually a panic:
| |
The bool short-circuits, the closure doesn’t. Whenever the value can panic, unwrap, or just costs real work, reach for then, not then_some.
When to reach for which
Use then_some(value) when the value is already computed or trivially cheap — a literal, a copy, a field access. Use then(|| value) whenever building the value costs something or could panic. Both are stable (then since Rust 1.50, then_some since 1.62) and both read cleaner than the if/else they replace.