Pouvez-vous créer une fonction qui prend une autre fonction et un paramètre et retourne un flux paresseux d'appels de fonctions imbriquées?

voix
6

En Clojure, j'utilise une fonction appelée iterateque:

Renvoie une séquence paresseuse de x, (fx), (f (fx)), etc. f doit être exempt d'effets secondaires

Y at-il quelque chose de similaire à Rust?

Par exemple, j'ai cette fonction que je voudrais passer à une fonction avec un nombre et puis itérer sur un flux / plage / vecteur jusqu'à ce que je trouve Some(1):

fn coltz(n: u64) -> Option<u64> {
    match n % 2 {
        0 => Some(n / 2), 
        _ => Some(3 * n + 1)
    }
}
Créé 20/10/2018 à 03:09
source utilisateur
Dans d'autres langues...                            


1 réponses

voix
7

Vous pouvez appeler à plusieurs reprises une fermeture à l' aide std::iter::repeat_with():

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

La valeur de retour est un itérateur sur les valeurs de retour successifs de la fermeture.

Nous utilisons movepour passer xdans la fermeture, que l'état actuel de notre itération. A l' intérieur de la fermeture , nous mettons à jour xavec f(x)et retourner la valeur ancienne (donc dans la première itération nous retourner l'original x).

Voici un exemple de travail complet:

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

Cour de récréation

Créé 20/10/2018 à 11:28
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more