How can I create what other languages call a lazy sequence or a \"generator\" function?
In Python, I can use yield as in the following example (from Pyt
As of Rust 1.34 stable, you have convenient std::iter::from_fn utility. It is not a coroutine (i.e. you still have to return each time), but at least it saves you from defining another struct.
from_fn accepts a closure FnMut() -> Option and repeatedly calls it to create an Iterator.
// -> Box> in Rust 2015
fn firstn(n: u64) -> impl std::iter::Iterator- {
let mut num = 0;
std::iter::from_fn(move || {
let result;
if num < n {
result = Some(num);
num += 1
} else {
result = None
}
result
})
}
fn main() {
let sum_of_first_n = firstn(1000000).sum::
();
println!("sum(0 to 999999): {}", sum_of_first_n);
}
std::iter::successors is also available. It is less general but might be a bit easier to use since you just pass around the seed value explicitly. (i.e. it takes an initial value T and a successor function FnMut(&T) -> Option to create an Iterator)
fn firstn(n: u64) -> impl std::iter::Iterator- {
std::iter::successors(
Some(0),
move |&num| {
if num + 1 < n {
Some(num + 1)
} else {
None
}
},
)
}
However, Shepmaster's note applies to these utility too. (tldr: often, hand-rolled Iterator is more memory efficient)
What's interesting about this is that it's less powerful than an implementation of
Iterator. For example, iterators have the size_hint method, which allows consumers of the iterator to have an idea of how many elements are remaining. This allows optimizations whencollecting into a container. Generators do not have any such information.
(Note: returning impl is a Rust 2018 feature. See the Edition Guide for details)