Extension traits
Един недостатък на нашите имплементации на адаптери за итератори (от упражнение 07), е че не са методи и не можем да ги навържем един след друг с method chaining.
// std
iter
.filter(|x| some_condition(x))
.map(|x| something(x));
// нашият код
let iter = my_filter(iter, |x| some_condition(x));
let iter = my_map(iter, |x| something(x));
iter
В такива случаи можем да си направим extension trait.
Trait-а IteratorExt:
- може да се имплементира само върху итератори, защото има trait bound
IteratorExt: Iterator - е имплементиран върху всички итератори, поради blanket impl блока на края
Например това се използва от пакета https://docs.rs/itertools/ за да добави още повече методи към итераторите.
trait IteratorExt: Iterator {
fn my_map<F, U>(self, func: F) -> Map<Self, F>
where
F: Fn(Self::Item) -> U,
Self: Sized,
{
iter_map(self, func)
}
fn my_filter<F>(self, func: F) -> Filter<Self, F>
where
F: Fn(&Self::Item) -> bool,
Self: Sized,
{
iter_filter(self, func)
}
}
impl<I> IteratorExt for I where I: Iterator {}
Това ни позволява да пишем
iter
.my_filter(|x| some_condition(x))
.my_map(|x| something(x))
