Presentando ?

A veces solo queremos la simplicidad de unwrap sin la posibilidad de un panic. Hasta ahora, unwrap nos ha obligado a anidar más y más profundamente cuando lo que realmente queríamos era extraer. Este es exactamente el propósito de ?.

Al encontrar un Err, hay dos acciones válidas para realizar:

  1. panic! que ya decidimos tratar de evitar si es posible
  2. return porque un Err significa que no se puede manejar

? es casi 1 exactamente equivalente a un unwrap que returna en lugar de panic en Errs. Veamos cómo podemos simplificar el ejemplo anterior que usaba combinadores:

use std::num::ParseIntError;

fn multiplica(primer_num_str: &str, segundo_num_str: &str) -> Result<i32, ParseIntError> {
    let primer_num = primer_num_str.parse::<i32>()?;
    let segundo_num = segundo_num_str.parse::<i32>()?;

    Ok(primer_num * segundo_num)
}

fn imprime(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    imprime(multiplica("10", "2"));
    imprime(multiplica("t", "2"));
}

El macro try!

Antes de que existiera ?, se lograba la misma funcionalidad con el macro try!. Ahora se recomienda el operador ?, pero aún puede encontrar try! al buscar en el código más antiguo. La misma función multiplica del ejemplo anterior se vería así usando try!:

// Para compilar y ejecutar este ejemplo sin errores, mientras usas Cargo,
// cambia el valor del campo `edition`, en la sección `[package]` del archivo
// `Cargo.toml`, a "2015".

use std::num::ParseIntError;

fn multiplica(primer_num_str: &str, segundo_num_str: &str) -> Result<i32, ParseIntError> {
    let primer_num = try!(primer_num_str.parse::<i32>());
    let segundo_num = try!(segundo_num_str.parse::<i32>());

    Ok(primer_num * segundo_num)
}

fn imprime(result: Result<i32, ParseIntError>) {
    match result {
        Ok(n)  => println!("n is {}", n),
        Err(e) => println!("Error: {}", e),
    }
}

fn main() {
    imprime(multiplica("10", "2"));
    imprime(multiplica("t", "2"));
}
1

Ve re-enter ? para más detalles.