Reputation: 474
Does the Rust standard library have a function that generates an infinite iterator given a seed and a lambda, as the Java 8 Streams provide? If not, what is a similar alternative in Rust?
Stream.iterate(1, x -> 2 * x);
Upvotes: 10
Views: 2174
Reputation: 3549
I wonder if
fn main() {
let x = (1..std::i32::MAX) .map(|x| x*2);
for i in x {
println!("{}", i);
}
}
would be a satisfactory option for you.
Upvotes: 0
Reputation: 5216
You can use standard scan
iterator:
let seq_gen = iter::repeat(())
.scan(1, |r,_|{
let out = *r; *r = out * 2 ; Some(out)
});
or with explicit closure definition:
let seq_gen = iter::repeat(())
.scan((1, |x| x*2), |r,_|{
let out = r.0; r.0 = r.1(r.0); Some(out)
});
For noncopyable types things looks worse:
let seq_gen = iter::repeat(())
.scan(Some("Hello world".to_owned()), |r,_|{
let out = r.clone(); *r = r.take().map(|x| x+"!") ; out
});
For these types it is better to use functions that modify the value in place:
let seq_gen = iter::repeat(())
.scan("Hello world".to_owned(), |r,_|{
let out = r.clone(); r.push_str("!") ; Some(out)
});
Upvotes: 2
Reputation: 430318
The Rust standard library used to have similar functionality under the name unfold
, but it was never made stable and was eventually removed. It now lives in the itertools crate:
extern crate itertools;
use itertools::Unfold;
fn main() {
let x = Unfold::new(1, |x| {
*x *= 2;
Some(*x)
});
for val in x.take(10) {
println!("{}", val);
}
}
Note that it's a bit more complicated because the state doesn't have to exactly match with what the iterator returns and you can control when the iterator stops. It's possible that the crate would accept a PR for a thin layer on top that gives your exact implementation.
Upvotes: 8
Reputation: 65692
As of Rust 1.7, there's nothing in Rust's standard library that does the equivalent of Stream.iterate
(or I couldn't find it!).
I just whipped up the following implementation in Rust. It's not as straightforward as the Java implementation might be, because we have to take care of ownership (hence the requirement for Clone
and the Option
dance with the value
field).
struct SequenceGenerator<T, F> {
value: Option<T>,
calc_next: F,
}
impl<T, F> SequenceGenerator<T, F>
where T: Clone,
F: FnMut(T) -> T
{
fn new(value: T, calc_next: F) -> SequenceGenerator<T, F> {
SequenceGenerator {
value: Some(value),
calc_next: calc_next,
}
}
}
impl<T, F> Iterator for SequenceGenerator<T, F>
where T: Clone,
F: FnMut(T) -> T
{
type Item = T;
fn next(&mut self) -> Option<T> {
let result = self.value.as_ref().unwrap().clone();
self.value = Some((self.calc_next)(self.value.take().unwrap()));
Some(result)
}
}
fn main() {
let seq_gen = SequenceGenerator::new(1, |x| 2 * x);
for i in seq_gen.take(10) {
println!("{}", i);
}
}
Upvotes: 7