AnyCompiler

Manejo de Errores

El operador ? es una forma abreviada de propagar un Result: si la expresión es Err, ? devuelve ese error inmediatamente desde la función actual; si es Ok, ? desenvuelve el valor y la ejecución continúa. Abajo, s.parse()? o bien te da un i32 válido o sale antes de tiempo de parse_and_double con el error de parseo.

use std::num::ParseIntError;

fn parse_and_double(s: &str) -> Result<i32, ParseIntError> {
    let n: i32 = s.parse()?;
    Ok(n * 2)
}

fn main() {
    match parse_and_double("21") {
        Ok(n) => println!("Doubled: {}", n),
        Err(e) => println!("Error: {}", e),
    }

    match parse_and_double("not a number") {
        Ok(n) => println!("Doubled: {}", n),
        Err(e) => println!("Error: {}", e),
    }
}
Output
Doubled: 42
Error: invalid digit found in string

Un tipo de error personalizado

Para tus propias funciones, un tipo de error personalizado — aunque sea tan simple como NegativeNumberError — suele ser más claro que reutilizar un error genérico. Implementar el trait Display para él es lo que permite que {} lo formatee directamente dentro de println!.

use std::fmt;

#[derive(Debug)]
struct NegativeNumberError;

impl fmt::Display for NegativeNumberError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "number must not be negative")
    }
}

fn square_root_ish(n: i32) -> Result<f64, NegativeNumberError> {
    if n < 0 {
        return Err(NegativeNumberError);
    }
    Ok((n as f64).sqrt())
}

fn main() {
    match square_root_ish(16) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }

    match square_root_ish(-4) {
        Ok(result) => println!("Result: {}", result),
        Err(e) => println!("Error: {}", e),
    }
}
Output
Result: 4
Error: number must not be negative

Siguiente: collections y la librería estándar — HashMap, y un vistazo final a qué más ofrece la librería estándar de Rust.

Practice Exercise

Escribe una función safe_divide(a: f64, b: f64) -> Result<f64, String> que devuelva Err("cannot divide by zero".to_string()) si b es 0.0, u Ok(a / b) en caso contrario. Llámala con (10.0, 0.0), haz match del resultado, e imprime el mensaje de error si es Err.