Result::and_then() works great for composing control flow.
fn some_fn() -> Result<String, Error> {
Ok("Yay".to_string())
}
some_fn()
.and_then(|value| some_other_fn())
.and_then(|some_other_value| /* ... */)
Sometimes we want to create a side effect and still propagate the emitted value. Let's say we want to print the value the moment we receive it:
some_fn()
.and_then(|value| {
println!("{}", &value);
some_other_fn()
})
.and_then(|some_other_value| /* ... */)
Is there a better way to do this? Something like Reactive Extensions' tap() operator would be great.
map and and_then are appropriate for when you want to transform the value. Using match or if let is appropriate for side effects:
let r = some_fn();
if let Ok(v) = &r {
println!("{}", v);
}
r.and_then(|_| some_other_fn())
See also:
Assuming that you only care about side effects when the Result is Ok...
You could also create an extension trait to add the desired method to Result. I'd advocate for calling it inspect as that's the name of the parallel method on Iterator.
trait InspectExt<T> {
fn inspect<F>(self, f: F) -> Self
where
F: FnOnce(&T);
}
impl<T, E> InspectExt<T> for Result<T, E> {
fn inspect<F>(self, f: F) -> Self
where
F: FnOnce(&T),
{
if let Ok(v) = &self {
f(v)
}
self
}
}
some_fn()
.inspect(|v| println!("{}", v))
.and_then(|_| some_fn())
See also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With