Can you create a function that takes another function and a parameter and returns a lazy stream of nested function calls?

前端 未结 2 359
时光说笑
时光说笑 2021-01-12 10:09

In Clojure, I use a function called iterate that:

Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects

2条回答
  •  耶瑟儿~
    2021-01-12 10:56

    You can repeatedly call a closure using std::iter::repeat_with():

    repeat_with(move || {
        let result = x;
        x = f(x);
        result
    })
    

    The return value is an iterator over the successive return values of the closure.

    We use move to move x into the closure, as the current state of our iteration. Inside the closure we update x with f(x) and return the old value (so in the first iteration we return the original x).

    Here is a complete working example:

    use std::iter::repeat_with;
    
    fn collatz(n: u64) -> u64 {
        match n % 2 {
            0 => n / 2,
            _ => 3 * n + 1,
        }
    }
    
    fn iterate(f: F, mut x: X) -> impl Iterator
    where
        F: Fn(X) -> X,
        X: Copy,
    {
        repeat_with(move || {
            let result = x;
            x = f(x);
            result
        })
    }
    
    fn main() {
        for i in iterate(collatz, 12).take_while(|&x| x != 1) {
            println!("{}", i);
        }
    }
    

    Playground

提交回复
热议问题