181. Option::get_or_insert_with — Lazy Default That Returns &mut
You have an Option<Vec<T>> field and want to push to it. If it’s None, allocate first; if it’s Some, just push. get_or_insert_with does both in one call — and hands you back a &mut so you can use it on the same line.
The dance you don’t have to do
The naïve version checks, assigns, then unwraps:
| |
Three lines, an unwrap, and you re-borrow the Option twice. get_or_insert_with collapses it:
| |
It initializes the Option to Some(f()) if and only if it was None, and returns &mut T to the inner value either way. No unwrap, no double-check.
The closure only runs when needed
That’s the whole point of the _with suffix: the default is lazy. If the value’s already there, your closure never fires, which matters when the default is expensive or has side effects:
| |
If your default is cheap (a String::new(), a 0u32), use the eager sibling get_or_insert and skip the closure:
| |
Why the &mut return matters
get_or_insert_with returns &mut T, not T or Option<T>. That lets you keep chaining — push, mutate, hand to another function — without ever re-borrowing the Option:
| |
The classic case is builders and config structs with Option<Vec<_>> fields that should only allocate when the caller actually adds something. One line per add, no upfront Some(Vec::new()), no unwrap.
Stable since Rust 1.20.