Можете ли вы создать функцию, которая принимает другую функцию и параметр и возвращает ленивый поток вызовов вложенных функций? - PullRequest
0 голосов
/ 20 октября 2018

В Clojure я использую функцию с именем iterate, которая:

Возвращает ленивую последовательность x, (fx), (f (fx)) и т. Д.f должен быть свободен от побочных эффектов

Есть ли что-то похожее в Rust?

Например, у меня есть эта функция, которую я хотел бы передать функции с номером, а затем перебрать поток / диапазон / вектор, пока не найду Some(1):

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

Ответы [ 2 ]

0 голосов
/ 11 апреля 2019

Начиная с 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
0 голосов
/ 20 октября 2018

Вы можете повторно вызывать замыкание, используя std::iter::repeat_with():

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

Возвращаемое значение является итератором последовательных возвращаемых значений замыкания.

Мы используем move для перемещения x в замыкание, как текущее состояние нашей итерации.Внутри замыкания мы обновляем 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);
    }
}

Детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...