Les closures

Ces exercices portent sur les fonctions anonymes, les fonctions d'ordre supérieur, la capture d'environnement et les traits Fn / FnMut. Faites-les dans l'ordre.

Appliquer n fois

Écrire une fonction qui applique n fois une fonction f à une valeur de départ : repeter(f, x, 3) vaut f(f(f(x))).

  • Objectif : paramètre F: Fn(i32) -> i32, boucle.
  • Signature suggérée : fn repeter<F: Fn(i32) -> i32>(f: F, x: i32, n: u32) -> i32.
  • Cas de test : repeter(|v| v + 1, 0, 5) -> 5, repeter(|v| v * 2, 1, 10) -> 1024, repeter(|v| v, 42, 0) -> 42.

Générateur (compteur)

Écrire une fonction qui renvoie une closure ; chaque appel de cette closure renvoie l'entier suivant, en commençant à 0.

  • Objectif : capture d'une variable mut, trait FnMut, impl FnMut() -> u32, move.
  • Signature suggérée : fn compteur() -> impl FnMut() -> u32.
  • Cas de test : let mut c = compteur(); puis c() -> 0, c() -> 1, c() -> 2.

Filtre paramétré

Écrire une fonction qui garde les éléments d'un slice satisfaisant un prédicat donné.

  • Objectif : impl Fn(&i32) -> bool en argument, construction d'un Vec.
  • Signature suggérée : fn garder(v: &[i32], pred: impl Fn(&i32) -> bool) -> Vec<i32>.
  • Cas de test : garder(&[1, 2, 3, 4, 5], |x| *x % 2 == 0) -> [2, 4], garder(&[1, 2, 3], |_| false) -> [].

Composer deux fonctions

Écrire composer(f, g) qui renvoie une closure x -> g(f(x)).

  • Objectif : deux paramètres génériques Fn, impl Fn(i32) -> i32 en retour, move.
  • Signature suggérée : fn composer<F, G>(f: F, g: G) -> impl Fn(i32) -> i32 where F: Fn(i32) -> i32, G: Fn(i32) -> i32.
  • Cas de test : let h = composer(|x| x + 1, |x| x * 3); h(2) -> 9.

Transformer une Option

À partir d'une Option<i32>, obtenir la valeur multipliée par 10 si elle existe, sinon -1, en une seule expression.

  • Objectif : Option::map, Option::unwrap_or.
  • Signature suggérée : fn dix_fois_ou_moins_un(o: Option<i32>) -> i32.
  • Cas de test : dix_fois_ou_moins_un(Some(4)) -> 40, dix_fois_ou_moins_un(None) -> -1.