En Rust, el manejo de errores es una parte fundamental del lenguaje, y se realiza de manera segura y eficiente. En esta sección, nos enfocaremos en el tipo Option, que se utiliza para representar valores que pueden o no estar presentes. Este tipo es muy útil para evitar errores comunes como los punteros nulos en otros lenguajes.

¿Qué es Option?

Option es una enumeración que puede tener dos variantes:

  • Some(T): Indica que hay un valor de tipo T.
  • None: Indica que no hay ningún valor.

Definición de Option

enum Option<T> {
    Some(T),
    None,
}

Uso Básico de Option

Ejemplo 1: Asignación y Verificación de Option

fn main() {
    let some_number = Some(5);
    let some_string = Some("Hello, Rust!");
    let absent_number: Option<i32> = None;

    println!("{:?}", some_number); // Output: Some(5)
    println!("{:?}", some_string); // Output: Some("Hello, Rust!")
    println!("{:?}", absent_number); // Output: None
}

Ejemplo 2: Acceso a Valores de Option

Para acceder al valor dentro de un Option, podemos usar patrones de coincidencia (match) o métodos como unwrap, expect, is_some, is_none, map, etc.

Usando match

fn main() {
    let some_number = Some(5);

    match some_number {
        Some(value) => println!("El valor es: {}", value),
        None => println!("No hay valor"),
    }
}

Usando unwrap y expect

fn main() {
    let some_number = Some(5);
    let absent_number: Option<i32> = None;

    println!("El valor es: {}", some_number.unwrap()); // Output: El valor es: 5
    // println!("El valor es: {}", absent_number.unwrap()); // Esto causará un pánico

    println!("El valor es: {}", some_number.expect("No se encontró un valor")); // Output: El valor es: 5
    // println!("El valor es: {}", absent_number.expect("No se encontró un valor")); // Esto causará un pánico con el mensaje "No se encontró un valor"
}

Métodos Comunes de Option

is_some y is_none

Estos métodos verifican si un Option contiene un valor (Some) o no (None).

fn main() {
    let some_number = Some(5);
    let absent_number: Option<i32> = None;

    println!("¿Tiene valor? {}", some_number.is_some()); // Output: ¿Tiene valor? true
    println!("¿Tiene valor? {}", absent_number.is_some()); // Output: ¿Tiene valor? false

    println!("¿Está vacío? {}", some_number.is_none()); // Output: ¿Está vacío? false
    println!("¿Está vacío? {}", absent_number.is_none()); // Output: ¿Está vacío? true
}

map

El método map permite aplicar una función a un valor dentro de un Option, si está presente.

fn main() {
    let some_number = Some(5);
    let absent_number: Option<i32> = None;

    let new_number = some_number.map(|x| x + 1);
    let new_absent_number = absent_number.map(|x| x + 1);

    println!("{:?}", new_number); // Output: Some(6)
    println!("{:?}", new_absent_number); // Output: None
}

Ejercicios Prácticos

Ejercicio 1: Uso de Option con match

Escribe una función que reciba un Option<i32> y devuelva el doble del valor si está presente, o None si no lo está.

fn double_option_value(opt: Option<i32>) -> Option<i32> {
    match opt {
        Some(value) => Some(value * 2),
        None => None,
    }
}

fn main() {
    let some_number = Some(5);
    let absent_number: Option<i32> = None;

    println!("{:?}", double_option_value(some_number)); // Output: Some(10)
    println!("{:?}", double_option_value(absent_number)); // Output: None
}

Ejercicio 2: Uso de Option con map

Escribe una función que reciba un Option<String> y devuelva la longitud de la cadena si está presente, o None si no lo está.

fn string_length(opt: Option<String>) -> Option<usize> {
    opt.map(|s| s.len())
}

fn main() {
    let some_string = Some(String::from("Hello, Rust!"));
    let absent_string: Option<String> = None;

    println!("{:?}", string_length(some_string)); // Output: Some(12)
    println!("{:?}", string_length(absent_string)); // Output: None
}

Resumen

En esta sección, hemos aprendido sobre el tipo Option en Rust, que se utiliza para manejar valores que pueden o no estar presentes. Hemos visto cómo definir y usar Option, cómo acceder a sus valores y cómo utilizar métodos comunes como is_some, is_none y map. También hemos practicado con ejercicios para reforzar estos conceptos.

En la siguiente sección, exploraremos el manejo de errores con el tipo Result, que es fundamental para la gestión de errores en Rust.

© Copyright 2024. Todos los derechos reservados