#iterator #output #iteration #perform #return

output_iter

An iterator that performs calculation during iteration

1 unstable release

0.1.0 Jan 12, 2025

#892 in Data structures

Download history 120/week @ 2025-01-08

120 downloads per month

MIT/Apache

22KB
412 lines

A utility for creating iterators that, in addition to yielding items, can perform a computation during iteration and return the result of that computation as soon as it is available.

Motivation

The OutputIterator is useful for scenarios where the result of a computation depends on iterated data and is not immediately available.

Without OutputIterator, you would rely on one of the following approaches:

  • Calculate everything in advance: Collect the iterator into a Vec, perform the computation, and then return the result along with an iterator over the vector. This approach is inefficient as it requires unnecessary memory allocations.
  • Introduce a "finishing" method: Add a method to the iterator to compute and return the result. However, this approach limits flexibility; for example, you couldn’t map the items of such an iterator since there is no such method on std::iter::Map.

Example

Here’s how you can use an OutputIterator to iterate over numbers, compute their sum, and retrieve the result as soon as the sum exceeds a certain threshold:

use output_iter::{OutputIterator, OutputIteratorVariant};

struct SumIterator {
    items: Vec<i32>,
    sum: i32,
    threshold: i32,
}

impl OutputIterator for SumIterator {
    type Item = i32;
    type Output = i32; // The computed sum
    type AfterOutput = std::vec::IntoIter<i32>;

    fn next(mut self) -> OutputIteratorVariant<Self> {
        use OutputIteratorVariant::*;
        
        if let Some(item) = self.items.pop() {
            self.sum += item;
            if self.sum >= self.threshold {
                Output(self.items.into_iter(), self.sum)
            } else {
                Next(self, item)
            }
        } else {
            Output(self.items.into_iter(), self.sum)
        }
    }
}

let iter = SumIterator {
    items: vec![1, 2, 3, 4, 5],
    sum: 0,
    threshold: 10,
};

let (remaining, result) = iter.until_output_iter(|before_iter| {
    for item in before_iter {
        println!("Processing item: {}", item);
    }
});

println!("Sum reached: {}", result);

for item in remaining {
    println!("Remaining item: {}", item);
}

Output

Processing item: 5
Processing item: 4
Processing item: 3
Sum reached: 12
Remaining item: 2
Remaining item: 1

No runtime deps