Rust中的函数是否等同于Java的Stream.Iterate?

时间:2016-03-10 05:35:26

标签: iterator rust

Rust标准库是否有一个函数可以在给定种子和lambda的情况下生成无限迭代器,就像Java 8 Streams提供的那样?如果没有,Rust中有哪些类似的替代方案?

Stream.iterate(1, x -> 2 * x);

4 个答案:

答案 0 :(得分:7)

从Rust 1.7开始,Rust标准库中的任何内容都没有Stream.iterate(或者我无法找到它!)。

我刚刚在Rust中发布了以下实现。它并不像Java实现那样简单,因为我们必须处理所有权(因此需要CloneOptionvalue字段共舞

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);
    }
}

答案 1 :(得分:7)

Rust标准库used在名称unfold下具有类似功能,但它从未稳定并最终被删除。它现在位于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);
    }
}

请注意,它有点复杂,因为状态不必与迭代器返回的内容完全匹配,您可以控制迭代器何时停止。该箱子可能会接受顶部薄层的PR,从而为您提供准确的实施。

答案 2 :(得分:1)

您可以使用标准scan迭代器:

let seq_gen = iter::repeat(())
                      .scan(1, |r,_|{
                          let out = *r; *r = out * 2 ; Some(out)
                      });

或使用显式闭包定义:

let seq_gen = iter::repeat(())
                      .scan((1, |x| x*2), |r,_|{
                          let out = r.0; r.0 = r.1(r.0); Some(out)
                      });

对于 noncopyable 类型,事情看起来更糟:

let seq_gen = iter::repeat(())
                      .scan(Some("Hello world".to_owned()), |r,_|{
                          let out = r.clone(); *r = r.take().map(|x| x+"!") ; out
                      });

对于这些类型,最好使用修改值的函数:

let seq_gen = iter::repeat(())
                      .scan("Hello world".to_owned(), |r,_|{
                          let out = r.clone(); r.push_str("!") ; Some(out)
                      });

答案 3 :(得分:0)

我想知道

fn main() {
    let x = (1..std::i32::MAX) .map(|x| x*2);

    for i in x {
        println!("{}", i);
    }
}

对您来说将是一个令人满意的选择。