Ce face Result
Rust nu are excepții. O funcție care poate eșua (citirea unui fișier, transformarea unui text în număr, o conexiune) returnează Result<T, E>: Ok(valoare) dacă a reușit, Err(eroare) dacă nu. T este tipul rezultatului, iar E tipul erorii.
Compilatorul te obligă să te uiți la rezultat: un Result ignorat produce avertismentul unused_must_use. Îl tratezi cu match, cu if let, cu metode precum unwrap_or și map_err sau îl trimiți mai departe cu operatorul ?.
is_ok() și is_err() răspund doar cu true/false, fără să scoată valoarea.
Parametri
| Parametru | Descriere |
|---|---|
T |
Tipul valorii la succes. |
E |
Tipul erorii: un text, std::io::Error, ParseIntError sau un tip propriu. |
Ce returnează
is_ok(): true pentru Ok. is_err(): true pentru Err.
Exemple
Exemplul 1: O funcție care poate eșua
Împărțirea la zero devine o eroare normală, tratată cu match, nu o oprire a programului.
fn imparte(suma: f64, persoane: u32) -> Result<f64, String> {
if persoane == 0 {
return Err(String::from("nu poți împărți la 0 persoane"));
}
Ok(suma / persoane as f64)
}
fn main() {
for persoane in [4, 0] {
match imparte(250.0, persoane) {
Ok(parte) => println!("{persoane} persoane: {parte:.2} lei de persoană"),
Err(e) => println!("Eroare: {e}"),
}
}
}
Rezultat
4 persoane: 62.50 lei de persoană
Eroare: nu poți împărți la 0 persoane
Exemplul 2: Result din biblioteca standard
parse returnează Result. Cu {:?} vezi și tipul de eroare.
fn main() {
let texte = ["42", "-7", "patru"];
for t in texte {
let r: Result<i32, _> = t.parse::<i32>();
println!("{t:>6}: is_ok = {:5}, is_err = {:5}, {r:?}", r.is_ok(), r.is_err());
}
}
Rezultat
42: is_ok = true , is_err = false, Ok(42)
-7: is_ok = true , is_err = false, Ok(-7)
patru: is_ok = false, is_err = true , Err(ParseIntError { kind: InvalidDigit })
Exemplul 3: Operatorul ? trimite eroarea mai departe
Dacă oricare parse eșuează, ? returnează imediat eroarea din aduna.
use std::num::ParseIntError;
fn aduna(a: &str, b: &str) -> Result<i32, ParseIntError> {
let x: i32 = a.trim().parse()?;
let y: i32 = b.trim().parse()?;
Ok(x + y)
}
fn main() {
println!("{:?}", aduna("10", " 32"));
println!("{:?}", aduna("10", "trei"));
}
Rezultat
Ok(42)
Err(ParseIntError { kind: InvalidDigit })
Greșeli frecvente
- Ignori un
Result:fs::write("a.txt", "x");dă avertismentulunused_must_use(eroare cu-D warnings). Tratează-l sau scrie explicitlet _ = ...;dacă chiar nu contează. - Folosești
?într-o funcție care returnează(): nu compilează. Funcția trebuie să returnezeResult(sauOption); șimainpoate returnaResult<(), E>. - Confunzi
ResultcuOption:Optionspune doar că lipsește ceva,Resultspune și de ce.
Comenzi înrudite
Result::unwrap: Scoate valoarea din Ok; pentru Err oprește programul cu panică. unwrap_err face invers: scoate eroarea.Result::map: map transformă valoarea din Ok și lasă eroarea neschimbată; map_err transformă eroarea și lasă valoarea neschimbată.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.Error: Trait-ul comun al tuturor tipurilor de eroare: o eroare se poate afișa (Display, Debug) și poate avea o cauză.Option: Tipul care spune „poate există o valoare, poate nu”: Some(valoare) sau None, în locul lui null din alte limbaje.