With this method we can write chains like this:
fn process_new(vec: Vec<String>) -> Option<i32> {
vec
.into_iter()
.map(|x| x.parse::<i32>())
.collect::<Result<Vec<_>, _>>().ok()?
.into_iter()
.sum::<i32>()
.apply(Some) // Usage of `apply` method
}
instead of this:
fn process_old(vec: Vec<String>) -> Option<i32> {
Some(vec // We must write `Some(` at start of chain
.into_iter()
.map(|x| x.parse::<i32>())
.collect::<Result<Vec<_>, _>>().ok()?
.into_iter()
.sum::<i32>()) // and `)` at end of chain
}
This method works like &
operator in Haskell. I think it might be useful for functional chains like this.
There was similar method called also
, it allows to run methods that returns ()
and requires &self
or &mut self
:
let val = 8.also_mut(|it| *it *= 2);
assert_eq!(val, 16);
There also deref
version of this method to make calls like this:
let sorted = vec![3, 2, 1].also_deref_mut(<[_]>::sort);
assert_eq!(sorted, vec![1, 2, 3]);
or
let pushed = vec![1, 2, 3].also_mut(|v| v.push(4));
assert_eq!(pushed, vec![1, 2, 3, 4]);
apply
method can be implemented by this code:
trait Apply: Sized {
fn apply<Res, F: FnOnce(Self) -> Res>(self, f: F) -> Res {
f(self)
}
}
impl<T: ?Sized> Apply for T {}
All examples and implementation of this methods you can find here.
I think it is useful and should be added to std
. Thougths?