iter::once în Rust

once(x) creează un iterator cu un singur element; empty() creează un iterator fără niciun element.

Sintaxă
pub fn once<T>(value: T) -> Once<T>
pub const fn empty<T>() -> Empty<T>

Ce face iter::once

std::iter::once(x) produce x o singură dată, apoi se termină. Este util pentru a adăuga un element la începutul sau sfârșitul unui lanț (once(antet).chain(randuri)) fără să creezi un vector.

std::iter::empty::<T>() nu produce nimic. Îl folosești acolo unde un API cere un iterator, dar nu ai elemente: suma lui este 0, count() este 0, iar collect dă o colecție goală.

Parametri

Parametru Descriere
value La once: singurul element produs.

Ce returnează

Once<T> (un element) sau Empty<T> (niciunul).

Exemple

Exemplul 1: Un element la început și la sfârșit

use std::iter::once;

fn main() {
    let orase = ["Ploiești", "Brașov", "Sibiu"];
    let traseu: Vec<&str> = once("București").chain(orase).chain(once("Cluj")).collect();
    println!("{}", traseu.join(" -> "));
}

Rezultat

București -> Ploiești -> Brașov -> Sibiu -> Cluj

Exemplul 2: empty: niciun element

use std::iter::empty;

fn main() {
    let nimic = empty::<u32>();
    println!("suma: {}", nimic.sum::<u32>());
    println!("număr: {}", empty::<&str>().count());
    let v: Vec<char> = empty().collect();
    println!("{:?}", v);
}

Rezultat

suma: 0
număr: 0
[]

Exemplul 3: once și empty în aceeași funcție

Ramurile unui if trebuie să aibă același tip. Cu Box<dyn Iterator> putem returna fie un iterator gol, fie unul cu un element, fie un interval.

use std::iter::{empty, once};

fn divizori(n: u32) -> Box<dyn Iterator<Item = u32>> {
    match n {
        0 => Box::new(empty()),
        1 => Box::new(once(1)),
        _ => Box::new((1..=n).filter(move |d| n % d == 0)),
    }
}

fn main() {
    for n in [0, 1, 12] {
        println!("{n}: {:?}", divizori(n).collect::<Vec<_>>());
    }
}

Rezultat

0: []
1: [1]
12: [1, 2, 3, 4, 6, 12]

Greșeli frecvente

  • Creezi un vector cu un element doar ca să-l lipești la un lanț (vec![x].into_iter()): alocă memorie. once(x) nu alocă.
  • Scrii empty() fără tip acolo unde nu se poate deduce: type annotations needed. Scrie empty::<u32>().

Comenzi înrudite

  • Iterator::chain: Lipește două șiruri de valori: produce întâi toate elementele primului, apoi pe ale celui de-al doilea.
  • iter::repeat: Creează un iterator care repetă la nesfârșit aceeași valoare; de obicei urmat de take(n).
  • iter::from_fn: Creează un iterator dintr-un closure: fiecare apel al closure-ului dă următorul element, iar None oprește iteratorul.
  • Iterator: Trait-ul care descrie orice șir de valori produse pe rând: next() dă următoarea valoare, sau None la final.