您是否可以创建一个接受另一个函数和一个参数并返回一个懒惰的嵌套函数调用流的函数?

时间:2018-10-20 03:09:37

标签: rust

在Clojure中,我使用了一个名为iterate的函数:

  

返回x,(f x),(f(f x))等的惰性序列。f必须没有副作用

Rust中是否有类似的东西?

例如,我想将此函数传递给带有数字的函数,然后遍历流/范围/向量,直到找到Some(1)

fn coltz(n: u64) -> Option<u64> {
    match n % 2 {
        0 => Some(n / 2), 
        _ => Some(3 * n + 1)
    }
}

2 个答案:

答案 0 :(得分:7)

您可以使用std::iter::repeat_with()反复调用闭包:

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

返回值是对闭包的连续返回值进行迭代的迭代器。

我们使用movex移至闭包中,作为迭代的当前状态。在闭包内部,我们用x更新f(x)并返回旧值(因此在第一次迭代中,我们返回原始的x)。

这是一个完整的工作示例:

use std::iter::repeat_with;

fn collatz(n: u64) -> u64 {
    match n % 2 {
        0 => n / 2,
        _ => 3 * n + 1,
    }
}

fn iterate<F, X>(f: F, mut x: X) -> impl Iterator<Item = X>
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

答案 1 :(得分:0)

从Rust 1.34开始,您可以使用iter::successors

fn coltz(n: u64) -> Option<u64> {
    match n % 2 {
        0 => Some(n / 2),
        _ => Some(3 * n + 1),
    }
}

use std::iter;

fn main() {
    let sequence = iter::successors(Some(10), |&v| coltz(v)).take_while(|&v| v != 1);
    for v in sequence {
        println!("{}", v);
    }
}
12
6
3
10
5
16
8
4
2