Option<T> and Result<T, E> in Depth
inspect() and inspect_err()
The .inspect(f) method on Option<T> and Result<T, E>, along with .inspect_err(f) on Result<T, E>, executes a side-effecting closure on a shared reference (&T or &E) to the inner value and returns the original Option or Result unchanged.
Signatures
impl<T> Option<T> {
pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self;
}
impl<T, E> Result<T, E> {
pub fn inspect<F: FnOnce(&T)>(self, f: F) -> Self;
pub fn inspect_err<F: FnOnce(&E)>(self, f: F) -> Self;
}
| Method | Available On | When Closure f Runs |
Parameter Passed to f |
Return Value |
|---|---|---|---|---|
opt.inspect(f) |
Option<T> |
Only when opt is Some(v) |
&T |
Original Option<T> |
res.inspect(f) |
Result<T, E> |
Only when res is Ok(v) |
&T |
Original Result<T, E> |
res.inspect_err(f) |
Result<T, E> |
Only when res is Err(e) |
&E |
Original Result<T, E> |
Logging and Metrics Inside Combinator or ? Chains
Before .inspect() and .inspect_err() were stabilized, logging an error right before propagating it with ? required writing .map_err(|e| { log(&e); e })?. With .inspect_err(), you can log or record metrics inline without returning e from the closure:
use std::num::ParseIntError;
fn parse_and_scale(raw: &str, factor: i32) -> Result<i32, ParseIntError> {
let scaled = raw
.trim()
.parse::<i32>()
.inspect(|val| println!(" [debug] parsed raw value: {val}"))
.inspect_err(|err| println!(" [error] failed to parse '{raw}': {err}"))?
* factor;
Ok(scaled)
}
fn main() {
println!("Result 1: {:?}", parse_and_scale(" 15 ", 4));
println!("Result 2: {:?}", parse_and_scale("abc", 4));
}
[debug] parsed raw value: 15
Result 1: Ok(60)
[error] failed to parse 'abc': invalid digit found in string
Result 2: Err(ParseIntError { kind: InvalidDigit })
Observing Option<T> Pipelines with .inspect()
fn main() {
let final_tag = Some(" Rust_2024 ")
.map(str::trim)
.inspect(|trimmed| println!("After trim: '{trimmed}'"))
.filter(|s| s.len() >= 5)
.map(str::to_lowercase);
println!("Final tag: {final_tag:?}");
}
After trim: 'Rust_2024'
Final tag: Some("rust_2024")