iter::successors în Rust

Creează un șir în care fiecare element se calculează din cel dinainte; se oprește când funcția returnează None.

Sintaxă
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
where F: FnMut(&T) -> Option<T>

Ce face iter::successors

successors(Some(primul), |x| ...) produce întâi primul, apoi rezultatul funcției aplicate pe el, apoi rezultatul aplicat pe acela și așa mai departe. Funcția primește o referință la elementul curent și returnează Some(urmatorul) sau None pentru oprire. Dacă primul argument este None, iteratorul este gol.

Este potrivit pentru puteri, dobânzi compuse, împărțiri repetate, șirul lui Collatz. Cu checked_mul / checked_add în funcție, șirul se oprește singur înainte de depășire.

Parametri

Parametru Descriere
first Primul element, în Some (sau None pentru un iterator gol).
succ Funcția care calculează următorul element din &curent.

Ce returnează

Un iterator Successors.

Exemple

Exemplul 1: Puterile lui 2 până la depășire

checked_mul dă None când rezultatul nu mai încape în u16, deci șirul se oprește singur.

use std::iter::successors;

fn main() {
    let puteri: Vec<u16> = successors(Some(1u16), |&x| x.checked_mul(2)).collect();
    println!("{} puteri: {:?}", puteri.len(), puteri);
}

Rezultat

16 puteri: [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768]

Exemplul 2: Economii cu dobândă de 5% pe an

use std::iter::successors;

fn main() {
    let ani = successors(Some(1000.0_f64), |s| Some(s * 1.05)).take(6);
    for (an, suma) in ani.enumerate() {
        println!("anul {an}: {suma:.2} lei");
    }
}

Rezultat

anul 0: 1000.00 lei
anul 1: 1050.00 lei
anul 2: 1102.50 lei
anul 3: 1157.62 lei
anul 4: 1215.51 lei
anul 5: 1276.28 lei

Exemplul 3: Șirul lui Collatz și cifrele unui număr

use std::iter::successors;

fn main() {
    let collatz: Vec<u64> = successors(Some(6u64), |&n| match n {
        1 => None,
        n if n % 2 == 0 => Some(n / 2),
        n => Some(3 * n + 1),
    })
    .collect();
    println!("{:?}", collatz);

    let cifre = successors(Some(2026u32), |&n| (n >= 10).then_some(n / 10)).count();
    println!("2026 are {cifre} cifre");
}

Rezultat

[6, 3, 10, 5, 16, 8, 4, 2, 1]
2026 are 4 cifre

Greșeli frecvente

  • Funcția returnează mereu Some și apelezi collect: iteratorul e infinit. Adaugă take sau o condiție de oprire.
  • Uiți că primul argument e un Option: successors(1, ..) nu compilează; scrie successors(Some(1), ..).

Comenzi înrudite

  • iter::from_fn: Creează un iterator dintr-un closure: fiecare apel al closure-ului dă următorul element, iar None oprește iteratorul.
  • Iterator::scan: Ca fold, dar produce câte un rezultat după fiecare element: o stare actualizată pas cu pas, de exemplu un total cumulat.
  • Iterator::take_while: take_while dă elemente cât timp condiția e adevărată și se oprește la primul care nu o îndeplinește; skip_while sare până atunci.
  • Iterator::fold: Combină toate elementele într-o singură valoare, pornind de la o valoare inițială și aplicând o funcție pas cu pas.