I want to extend generic iterators with a convenience function until()
that works like an inversion of take_while()
.
Here is the code:
Cargo.toml
:
[package]
name = "until"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
src/lib.rs
:
use std::iter::TakeWhile;
pub trait Until<T, P>: Iterator<Item = T> + Sized
where
P: Fn(&Self::Item) -> bool + 'static,
{
fn until(&mut self, f: P) -> TakeWhile<&mut Self, Box<dyn Fn(&T) -> bool>> {
self.take_while(Box::new(move |item| !f(item)))
}
}
impl<T, P, I> Until<T, P> for I
where
P: Fn(&Self::Item) -> bool + 'static,
I: Iterator<Item = T>,
{
}
src/main.rs
:
use until::Until;
fn main() {
let items = vec![1, 2, 3, 4, 5];
for item in items.into_iter().until(|item| *item > 3) {
println!("{}", item);
}
}
What I don't like about this implementation are
- The use of a
Box
to wrap the function pointer - The thus resulting complex return type of
until()
- The fact that I explicitly need to implement the trait for all iterators in an empty
impl
block
How can I address these three issues (and possibly others)?