Simplificando el manejo de Option en Rust con Map

RustRustBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, exploramos el uso del combinador map() en Rust para simplificar el flujo de control y manejar tipos Option de manera concisa y modular.

Nota: Si el laboratorio no especifica un nombre de archivo, puede usar cualquier nombre de archivo que desee. Por ejemplo, puede usar main.rs, compilar y ejecutarlo con rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/ErrorHandlingandDebuggingGroup(["Error Handling and Debugging"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/ErrorHandlingandDebuggingGroup -.-> rust/error_propagation("Error Propagation") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/function_syntax -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/expressions_statements -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/lifetime_specifiers -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/method_syntax -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/error_propagation -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} rust/operator_overloading -.-> lab-99236{{"Simplificando el manejo de Option en Rust con Map"}} end

Combinadores: map

match es un método válido para manejar Options. Sin embargo, es posible que eventualmente encuentres que su uso intensivo es tedioso, especialmente con operaciones que solo son válidas con una entrada. En estos casos, los combinadores se pueden utilizar para manejar el flujo de control de manera modular.

Option tiene un método integrado llamado map(), un combinador para la simple asignación de Some -> Some y None -> None. Se pueden encadenar múltiples llamadas a map() para mayor flexibilidad.

En el siguiente ejemplo, process() reemplaza a todas las funciones anteriores mientras se mantiene compacta.

#![allow(dead_code)]

#[derive(Debug)] enum Food { Apple, Carrot, Potato }

#[derive(Debug)] struct Peeled(Food);
#[derive(Debug)] struct Chopped(Food);
#[derive(Debug)] struct Cooked(Food);

// Pelando la comida. Si no hay ninguna, entonces devuelve `None`.
// De lo contrario, devuelve la comida pelada.
fn peel(food: Option<Food>) -> Option<Peeled> {
    match food {
        Some(food) => Some(Peeled(food)),
        None       => None,
    }
}

// Cortando la comida. Si no hay ninguna, entonces devuelve `None`.
// De lo contrario, devuelve la comida cortada.
fn chop(peeled: Option<Peeled>) -> Option<Chopped> {
    match peeled {
        Some(Peeled(food)) => Some(Chopped(food)),
        None               => None,
    }
}

// Cocinando la comida. Aquí, mostramos `map()` en lugar de `match` para el manejo de casos.
fn cook(chopped: Option<Chopped>) -> Option<Cooked> {
    chopped.map(|Chopped(food)| Cooked(food))
}

// Una función para pelar, cortar y cocinar la comida en secuencia.
// Encadenamos múltiples usos de `map()` para simplificar el código.
fn process(food: Option<Food>) -> Option<Cooked> {
    food.map(|f| Peeled(f))
     .map(|Peeled(f)| Chopped(f))
     .map(|Chopped(f)| Cooked(f))
}

// Comprueba si hay comida o no antes de intentar comerla!
fn eat(food: Option<Cooked>) {
    match food {
        Some(food) => println!("Mmm. I love {:?}", food),
        None       => println!("Oh no! It wasn't edible."),
    }
}

fn main() {
    let apple = Some(Food::Apple);
    let carrot = Some(Food::Carrot);
    let potato = None;

    let cooked_apple = cook(chop(peel(apple)));
    let cooked_carrot = cook(chop(peel(carrot)));
    // Probemos ahora la más simple de aspecto `process()`.
    let cooked_potato = process(potato);

    eat(cooked_apple);
    eat(cooked_carrot);
    eat(cooked_potato);
}

Resumen

¡Felicitaciones! Has completado el laboratorio Combinadores: Map. Puedes practicar más laboratorios en LabEx para mejorar tus habilidades.