Result::map în Rust

map transformă valoarea din Ok și lasă eroarea neschimbată; map_err transformă eroarea și lasă valoarea neschimbată.

Sintaxă
fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E>
fn map_err<F2, O: FnOnce(E) -> F2>(self, op: O) -> Result<T, F2>

Ce face Result::map

map aplică funcția pe valoarea din Ok. Err trece neatins. Este util când vrei să procesezi rezultatul unei operații care poate eșua, fără să scrii un match.

map_err face invers: transformă doar eroarea. Se folosește foarte des înainte de ?, ca să transformi o eroare din biblioteca standard într-un mesaj clar sau în tipul tău de eroare: text.parse().map_err(|e| format!("nota invalidă: {e}"))?.

Parametri

Parametru Descriere
op Funcția aplicată valorii din Ok (la map) sau erorii din Err (la map_err).

Ce returnează

Un nou Result, cu valoarea sau eroarea transformată.

Exemple

Exemplul 1: map pe valoare, map_err pe eroare

fn main() {
    for text in ["25", "-x"] {
        let dublu = text.parse::<i32>().map(|n| n * 2);
        let mesaj = text.parse::<i32>().map_err(|e| format!("„{text}” nu e număr: {e}"));
        println!("map:     {dublu:?}");
        println!("map_err: {mesaj:?}");
    }
}

Rezultat

map:     Ok(50)
map_err: Ok(25)
map:     Err(ParseIntError { kind: InvalidDigit })
map_err: Err("„-x” nu e număr: invalid digit found in string")

Exemplul 2: Eroare clară înainte de ?

map_err transformă ParseIntError într-un String, ca să se potrivească cu tipul de eroare al funcției.

fn citeste_varsta(text: &str) -> Result<u8, String> {
    let v: u8 = text
        .trim()
        .parse()
        .map_err(|e| format!("vârsta „{}” este invalidă ({e})", text.trim()))?;
    if v < 18 {
        return Err(format!("trebuie să ai cel puțin 18 ani, ai {v}"));
    }
    Ok(v)
}

fn main() {
    for t in ["34", "15", "300", "ani"] {
        match citeste_varsta(t) {
            Ok(v) => println!("OK: {v} ani"),
            Err(e) => println!("Eroare: {e}"),
        }
    }
}

Rezultat

OK: 34 ani
Eroare: trebuie să ai cel puțin 18 ani, ai 15
Eroare: vârsta „300” este invalidă (number too large to fit in target type)
Eroare: vârsta „ani” este invalidă (invalid digit found in string)

Greșeli frecvente

  • Folosești map cu o funcție care returnează tot Result: obții Result<Result<..>, E>. Folosește and_then.
  • Scrii ? între tipuri de eroare diferite fără conversie: dacă nu există From între ele, transformă eroarea cu map_err.

Comenzi înrudite

  • Result::and_then: and_then continuă cu următorul pas care poate eșua doar dacă cel curent a reușit; or_else încearcă o recuperare la eroare.
  • Option::map: Transformă valoarea din Some cu o funcție și păstrează None neschimbat.
  • Result: Tipul pentru operații care pot eșua: Ok(valoare) la succes sau Err(eroare) cu motivul eșecului.
  • Error: Trait-ul comun al tuturor tipurilor de eroare: o eroare se poate afișa (Display, Debug) și poate avea o cauză.