Ce face Option::and_then
and_then seamănă cu map, dar funcția dată returnează un Option. Astfel poți înlănțui pași care pot eșua fiecare: dacă oricare dă None, rezultatul final este None și pașii următori nu mai rulează.
Rezultatul nu este „împachetat de două ori”: dacă funcția returnează Some(y), obții Some(y), nu Some(Some(y)). În alte limbaje operația se numește flatMap sau bind.
Într-o funcție care returnează ea însăși Option, aceeași înlănțuire se scrie adesea mai clar cu operatorul ?.
Parametri
| Parametru | Descriere |
|---|---|
f |
Funcția aplicată valorii din Some; returnează Option<U>. |
Ce returnează
None dacă opțiunea este None; altfel, exact ce returnează f(x).
Exemple
Exemplul 1: Pași care pot eșua fiecare
Întâi găsim elevul, apoi îi citim nota. Al doilea pas returnează și el Option, deci folosim and_then.
fn id_elev(nume: &str) -> Option<u32> {
match nume {
"Ana" => Some(1),
"Mihai" => Some(2),
_ => None,
}
}
fn nota_dupa_id(id: u32) -> Option<u8> {
if id == 1 { Some(10) } else { None }
}
fn main() {
for nume in ["Ana", "Mihai", "Ioana"] {
let nota = id_elev(nume).and_then(nota_dupa_id);
println!("{nume}: {nota:?}");
}
}
Rezultat
Ana: Some(10)
Mihai: None
Ioana: None
Exemplul 2: Diferența față de map
Cu map, funcția care returnează Option dă un Option în Option; and_then îl „aplatizează”.
fn main() {
let text: Option<&str> = Some("42");
let cu_map: Option<Option<i32>> = text.map(|t| t.parse().ok());
let cu_and_then: Option<i32> = text.and_then(|t| t.parse().ok());
println!("map: {cu_map:?}");
println!("and_then: {cu_and_then:?}");
let gresit: Option<&str> = Some("patru");
println!("text invalid: {:?}", gresit.and_then(|t| t.parse::<i32>().ok()));
}
Rezultat
map: Some(Some(42))
and_then: Some(42)
text invalid: None
Greșeli frecvente
- Folosești
and_thencu o funcție care returnează o valoare simplă: nu compilează. Pentru asta emap. - Faci lanțuri foarte lungi de
and_thencu closure-uri imbricate. Într-o funcție care returneazăOption, operatorul?este mai ușor de citit.
Comenzi înrudite
Option::map: Transformă valoarea din Some cu o funcție și păstrează None neschimbat.Option::or: Dacă opțiunea este None, încearcă altă opțiune; Some rămâne neschimbat. or_else calculează alternativa doar la nevoie.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::filter: filter păstrează valoarea doar dacă respectă o condiție; is_some_and întreabă direct dacă există și respectă condiția.