Iterator::by_ref în Rust

Împrumută iteratorul în loc să-l consume, ca să poți folosi un adaptor pe o parte din el și să continui apoi cu restul.

Sintaxă
fn by_ref(&mut self) -> &mut Self

Ce face Iterator::by_ref

Majoritatea adaptoarelor (take, take_while, for) primesc iteratorul prin valoare și îl consumă. by_ref() returnează o referință mutabilă la iterator; cum &mut I este tot un iterator, adaptorul lucrează prin referință, iar iteratorul original rămâne utilizabil după aceea, de unde a rămas.

Este util când un text sau un flux are părți diferite: citești antetul cu by_ref().take(n), apoi procesezi restul liniilor altfel.

Ce returnează

&mut Self.

Exemple

Exemplul 1: Primele 2, apoi restul

fn main() {
    let mut it = ["Ana", "Mihai", "Ioana", "Radu", "Elena"].into_iter();
    let podium: Vec<&str> = it.by_ref().take(2).collect();
    let restul: Vec<&str> = it.collect();
    println!("primii doi: {:?}", podium);
    println!("ceilalți:   {:?}", restul);
}

Rezultat

primii doi: ["Ana", "Mihai"]
ceilalți:   ["Ioana", "Radu", "Elena"]

Exemplul 2: Antetul și corpul unui fișier

take_while prin by_ref consumă și linia goală care îl oprește, așa că restul începe direct cu corpul.

fn main() {
    let fisier = "titlu: Raport\nautor: Ana\n\nVânzările au crescut.\nCheltuielile au scăzut.";
    let mut linii = fisier.lines();
    let antet: Vec<&str> = linii.by_ref().take_while(|l| !l.is_empty()).collect();
    println!("antet: {:?}", antet);
    for (i, l) in linii.enumerate() {
        println!("rândul {}: {l}", i + 1);
    }
}

Rezultat

antet: ["titlu: Raport", "autor: Ana"]
rândul 1: Vânzările au crescut.
rândul 2: Cheltuielile au scăzut.

Greșeli frecvente

  • Scrii let primele: Vec<_> = it.take(2).collect(); și apoi vrei să folosești it: use of moved value: `it`. Folosește it.by_ref().take(2).
  • Uiți că iteratorul trebuie declarat mut: by_ref cere &mut self.

Comenzi înrudite

  • Iterator::take: take(n) produce cel mult primele n elemente; skip(n) sare peste primele n și produce restul.
  • 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::peekable: Transformă iteratorul într-un Peekable, care te lasă să te uiți la următorul element (peek) fără să-l consumi.
  • Iterator: Trait-ul care descrie orice șir de valori produse pe rând: next() dă următoarea valoare, sau None la final.