Menu
Coddy logo textTech

El Enum Option revisitado

Parte de la sección Object Oriented Programming del Journey de Rust de Coddy — lección 17 de 61.

Ya te has encontrado con Option<T> en Rust; es el enum estándar para representar valores que pueden existir o no. Ahora veámoslo a través de una lente de OOP: Option no es solo un enum, es un tipo con potentes métodos integrados que te permiten manejar valores nulos de forma segura y elegante.

En lugar de usar coincidencia de patrones cada vez, puedes usar métodos directamente en valores Option. El método unwrap_or devuelve el valor interno si existe, o un valor predeterminado que proporciones:

let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name);  // Alice

let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback);  // Guest

El método map transforma el valor interno si existe, dejando None sin cambios. Esto te permite encadenar operaciones sin tener que comprobar constantemente None:

let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled);  // Some(10)

let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing);  // None

Estos métodos encarnan los principios de la OOP: el tipo Option encapsula el concepto de "tal vez un valor" y proporciona una interfaz limpia para trabajar con él. Se llaman a los métodos en el objeto en lugar de escribir lógica externa para inspeccionarlo.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de perfil de usuario que maneje con elegancia los datos opcionales utilizando métodos de Option. Los usuarios pueden tener un apodo establecido o no; tu sistema manejará ambos casos de forma elegante sin necesidad de un emparejamiento explícito.

Crearás dos archivos para organizar tu código:

  • profile.rs: Define una estructura pública Profile con dos campos: username (String) y nickname (Option<String>). Implementa:
    • Un constructor new que reciba un nombre de usuario y un apodo opcional
    • Un método display_name que devuelva el apodo si existe, o el nombre de usuario como alternativa; utiliza unwrap_or para manejar esto
    • Un método formatted_nickname que devuelva un Option<String> con el apodo envuelto entre corchetes (como "[CoolNick]") si existe, o None si no hay apodo; utiliza map para transformar el valor
  • main.rs: Incorpora tu módulo de perfil y crea dos perfiles: uno con apodo y otro sin él. Demuestra ambos métodos en cada perfil para mostrar cómo los métodos de Option manejan los valores presentes y ausentes de manera diferente.

Para el método formatted_nickname, utiliza el formato de depuración ({:?}) al imprimir, ya que devuelve un Option.

Tu salida debe seguir este formato exacto, mostrando ambos perfiles:

Display name: {name}
Formatted nickname: {option}
Display name: {name}
Formatted nickname: {option}

Por ejemplo, con un perfil para el nombre de usuario "alice" con el apodo "Ace", y otro para el nombre de usuario "bob" sin apodo, la salida sería:

Display name: Ace
Formatted nickname: Some("[Ace]")
Display name: bob
Formatted nickname: None

Recibirás tres entradas: el primer nombre de usuario, el apodo del primer usuario y el segundo nombre de usuario (que no tiene apodo).

Hoja de referencia

El tipo Option<T> proporciona métodos para trabajar con valores opcionales sin necesidad de una coincidencia explícita.

El método unwrap_or devuelve el valor interno si existe, o un valor predeterminado si es None:

let maybe_name: Option<String> = Some(String::from("Alice"));
let name = maybe_name.unwrap_or(String::from("Guest"));
println!("{}", name);  // Alice

let empty: Option<String> = None;
let fallback = empty.unwrap_or(String::from("Guest"));
println!("{}", fallback);  // Guest

El método map transforma el valor interno si existe, dejando None sin cambios:

let maybe_num: Option<i32> = Some(5);
let doubled = maybe_num.map(|x| x * 2);
println!("{:?}", doubled);  // Some(10)

let nothing: Option<i32> = None;
let still_nothing = nothing.map(|x| x * 2);
println!("{:?}", still_nothing);  // None

Estos métodos permiten encadenar operaciones sobre valores Option sin tener que comprobar constantemente si es None.

Pruébalo tú mismo

mod profile;

use profile::Profile;

fn main() {
    // Leer entradas
    let mut input1 = String::new();
    std::io::stdin().read_line(&mut input1).expect("Failed to read line");
    let username1 = input1.trim().to_string();

    let mut input2 = String::new();
    std::io::stdin().read_line(&mut input2).expect("Failed to read line");
    let nickname1 = input2.trim().to_string();

    let mut input3 = String::new();
    std::io::stdin().read_line(&mut input3).expect("Failed to read line");
    let username2 = input3.trim().to_string();

    // TODO: Crear el primer perfil con username1 y nickname1 (Some)
    
    // TODO: Crear el segundo perfil con username2 y sin apodo (None)
    
    // TODO: Imprimir display_name y formatted_nickname para el primer perfil
    // Usa {:?} para formatted_nickname ya que devuelve un Option
    
    // TODO: Imprimir display_name y formatted_nickname para el segundo perfil
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming