0 day streak
rust / expert
Snippet

Constructing Custom Lazy Array Filter Combinators

This example shows how to design a custom iterator that lazily processes an array slice using a predicate function, avoiding intermediate allocations and implementing pipeline-based control flow manually.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
struct LazyFilter<'a, T, F> {
slice: &'a [T],
predicate: F,
index: usize,
}
impl<'a, T, F> LazyFilter<'a, T, F>
where
F: Fn(&T) -> bool,
{
fn new(slice: &'a [T], predicate: F) -> Self {
Self { slice, predicate, index: 0 }
}
}
impl<'a, T, F> Iterator for LazyFilter<'a, T, F>
where
F: Fn(&T) -> bool,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
while self.index < self.slice.len() {
let element = &self.slice[self.index];
self.index += 1;
if (self.predicate)(element) {
return Some(element);
}
}
None
}
}
fn process_data() -> Vec<i32> {
let numbers = [1, 2, 3, 4, 5, 6];
let filter = LazyFilter::new(&numbers, |&x| x % 2 == 0);
filter.copied().collect()
}
Breakdown
1
struct LazyFilter<'a, T, F>
Holds a lifetime-bound slice reference, a generic predicate closure, and the current index offset.
2
impl<'a, T, F> Iterator for LazyFilter
Implements the Iterator trait to enable integration with Rust's standard loop controls.
3
while self.index < self.slice.len()
Loops sequentially through the internal elements without allocating memory dynamically.
4
if (self.predicate)(element)
Invokes the predicate closure to determine if the reference should be returned or skipped.