Extraer Results de Options

La forma más básica de manejar tipos de errores mixtos es simplemente incrustarlos entre sí.

use std::num::ParseIntError;

fn duplica_primer_elemento(vec: Vec<&str>) -> Option<Result<i32, ParseIntError>> {
    vec.first().map(|first| {
        first.parse::<i32>().map(|n| 2 * n)
    })
}

fn main() {
    let numeros = vec!["42", "93", "18"];
    let vacio = vec![];
    let cadenas = vec!["tofu", "93", "18"];

    println!("El doble del primer elemento es {:?}", duplica_primer_elemento(numeros));

    println!("El doble del primer elemento es {:?}", duplica_primer_elemento(vacio));
    // Error 1: el vector de entrada está vacío

    println!("El doble del primer elemento es {:?}", duplica_primer_elemento(cadenas));
    // Error 2: el elemento no se analiza a un número
}

Hay ocasiones en las que queremos detener el procesamiento de errores (como con ?) pero continuar cuando la Option sea None. Un par de combinadores son útiles para intercambiar el Result y la Option.

use std::num::ParseIntError;

fn duplica_primer_elemento(vec: Vec<&str>) -> Result<Option<i32>, ParseIntError> {
    let opt = vec.first().map(|first| {
        first.parse::<i32>().map(|n| 2 * n)
    });

    opt.map_or(Ok(None), |r| r.map(Some))
}

fn main() {
    let numeros = vec!["42", "93", "18"];
    let vacio = vec![];
    let cadenas = vec!["tofu", "93", "18"];

    println!("El primer elemento duplicado es {:?}", duplica_primer_elemento(numeros));
    println!("El primer elemento duplicado es {:?}", duplica_primer_elemento(vacio));
    println!("El primer elemento duplicado es {:?}", duplica_primer_elemento(cadenas));
}