迭代连续折叠结果的惯用和功能方法是什么?

What is the idiomatic and functional way to iterate over successive fold results?

我有一个序列(列表,迭代器)a0, a1, a2, ...,我用一个函数f来折叠。我想要一个能给我

的发电机
a0, f(a0, a1), f(f(a0, a1), a2), ...

这类似于 Mathematica 中的 FoldList。有可用的 fold_list 功能吗?我没找到。

我想说最接近的抽象是 Iterator::scan。它更强大一点,因为它有一个内部可变状态(即可以为生成的迭代器产生不同的值)并且可以提前中止。

您可以像这样使用它来构建迭代器扩展特征:

Playground

pub trait FoldListExt: Iterator {
    fn fold_list<'a, St: 'a, F: 'a>(self, initial_state: St, f: F) -> Box<Iterator<Item = St> + 'a>
    where
        St: Clone,
        F: FnMut(St, Self::Item) -> St,
        Self: 'a;
}

impl<I: Iterator> FoldListExt for I {
    fn fold_list<'a, St: 'a, F: 'a>(
        self,
        initial_state: St,
        mut f: F,
    ) -> Box<Iterator<Item = St> + 'a>
    where
        St: Clone,
        F: FnMut(St, Self::Item) -> St,
        Self: 'a,
    {
        Box::new(self.scan(Some(initial_state), move |state, item| {
            let old_state = state.take().unwrap();
            *state = Some(f(old_state.clone(), item));
            Some(old_state)
        }))
    }
}

pub fn main() {
    println!(
        "{:?}",
        (0..16)
            .into_iter()
            .fold_list(0, |a, b| a + b)
            .collect::<Vec<_>>()
    );
}

我使用 Option<St> 作为内部可变状态以避免另一个 clone() 调用。

您可以改用这个:

Box::new(self.scan(initial_state, move |state, item| {
    let old_state = state.clone();
    *state = f(old_state.clone(), item);
    Some(old_state)
}))