I would like to avoid experimental features so I am considering other options before generators.
I have a vector v which is delimited into groups by 0. The sum of these delimited groups can be accumulated through a for loop or an iterator:
fn main() { let v = vec![55, 23, 75, 0, 12, 34, 0, 97, 71, 23, 0]; // for loop let mut acc = 0; for &vi in &v { acc += vi; if vi == 0 { println!("for yield {}", acc); acc = 0; } } // iter 'loop' v.iter() .scan(0, |acc, &vi| { *acc += vi; Some(if vi == 0 { let total = *acc; *acc = 0; Some(total) } else { None }) }) .filter_map(|acc| acc) .for_each(|acc| println!("iter yield {:?}", acc)); } scan is used as an ad hoc coroutine which returns Some(value) when the iterator has produced a value and None when the iterator is still processing. None is filtered out and the sums are printed.
The example above is somewhat trivial as both operations produce the same result; however, my project requires digesting a stream of data (cannot be collected into vector) and conditionally folding them (e.g. a condition here could be if the acc is divisible by 10, instead of 0 delimited).
The folding condition itself is pipelined such that each pipeline may provide an iterator (think nested coroutines). I'd like to see if there is an alternative to Iterator::scan -> Iterator::filter_map whether they use iterators or not. Keep in mind, collecting the entire stream of data is not possible as the stream is potentially unlimited.
v.split(|vi| vi == 0)and then you can use.map(|g| g.sum())or similar. I don't of a better solution for splitting based on the sum itself though.scan. How isscanused like a coroutine here? A coroutine should either be able to suspend execution or switch it to someone else, and your code does neither, it's an ordinary subroutine. The title also refers to coroutines without explaining the connection.