Option Combinators
Option provides combinators to transform and chain optional values without nested match.
Recipe
fn port_from_env() -> Option<u16> {
std::env::var("PORT").ok()
.and_then(|s| s.parse().ok())
}When to reach for this: Pipelines where absence is normal, not an error requiring Result.
Working Example
struct User { name: String, nickname: Option<String> }
fn display_name(u: &User) -> String {
u.nickname.as_ref()
.map(|n| format!("{} ({})", u.name, n))
.unwrap_or_else(|| u.name.clone())
}
fn main() {
let u = User { name: "Ada".into(), nickname: Some("ad".into()) };
println!("{}", display_name(&u));
}What this demonstrates:
map/as_refavoid movingunwrap_or_elselazy default- Optional field handling without panic
Deep Dive
Key methods: map, and_then, filter, or, or_else, unwrap_or, unwrap_or_default, ok_or, transpose, zip.
Gotchas
- unwrap in production - Panics on
None. Fix:unwrap_oror?withok_or. - Moving with
mapon owned Option - Consumes. Fix:as_ref/as_mut. - Nested Option<Option<T>> -
flatten(1.29+). - Confusing
andvsand_then-andreplaces with constant Option. Fix: Read docs per method. - Option vs Result - Use
ok_orwhen absence is error.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
match | Complex branches | Simple map chain |
if let | One pattern | Long combinator chain |
Result | Need error reason | Legitimate absence |
MaybeUninit | uninitialized (unsafe) | Normal optional value |
FAQs
? on Option?
In functions returning Option only.collect Option?
Not common - use Result collect.zip?
Pair two Options if both Some.replace?
Take value leaving None.take?
Move out leaving None.transpose Result?
Result<Option<T>,E> <-> Option<Result<T,E>>.async Option?
Combine with futures OptionExt crates if needed.clippy?
manual_flatten etc.serde Option?
Skips None fields by default.Default?
unwrap_or_default needs T: Default.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.