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);
Remember that loops use an imperative style and Streams a declarative style, so Streams are likely to be much easier to maintain. If you have a small list, loops perform better. If you have a huge list, a parallel stream will perform better.
Iterators, in Java, are used in Collection Framework to retrieve elements one by one. A stream in Java is a pipeline of objects from an array or a collection data source. A sequential stream is one in which the objects are pipelined in a single stream on the same processing system.
List interface provides a stream() method which gives a stream to iterate using forEach method. In forEach method, we can use the lambda expression to iterate over all elements. The following code snippet shows the usage of streams to iterate over the list.
iterator() . The latter will process all items of the stream in order to store them into a collection. In contrast, Stream. iterator() will just return a wrapper around the Stream 's Spliterator which will process all items lazily like all other stream operations do.
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.
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)
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With