Desestructuración

Al igual que las tuplas, las estructuras y las enumeraciones también se pueden desestructurar con la coincidencia:

Structs

struct Foo {
    x: (u32, u32),
    y: u32,
}

#[rustfmt::skip]
fn main() {
    let foo = Foo { x: (1, 2), y: 3 };
    match foo {
        Foo { x: (1, b), y } => println!("x.0 = 1, b = {b}, y = {y}"),
        Foo { y: 2, x: i }   => println!("y = 2, x = {i:?}"),
        Foo { y, .. }        => println!("y = {y}, se han ignorado otros campos"),
    }
}

Enumeraciones

Los patrones también se pueden usar para enlazar variables a partes de los valores. Así es como se inspecciona la estructura de tus tipos. Empecemos con un tipo enum sencillo:

enum Result {
    Ok(i32),
    Err(String),
}

fn divide_in_two(n: i32) -> Result {
    if n % 2 == 0 {
        Result::Ok(n / 2)
    } else {
        Result::Err(format!("no se puede dividir {n} en dos partes iguales"))
    }
}

fn main() {
    let n = 100;
    match divide_in_two(n) {
        Result::Ok(half) => println!("{n} dividido entre dos es {half}"),
        Result::Err(msg) => println!("se ha producido un error: {msg}"),
    }
}

Aquí hemos utilizado los brazos para desestructurar el valor de Result. En el primer brazo, half está vinculado al valor que hay dentro de la variante Ok. En el segundo, msg está vinculado al mensaje de error.

This slide should take about 10 minutes.

Structs

  • Cambia los valores literales de foo para que coincidan con los demás patrones.
  • Añade un campo nuevo a Foo y realiza los cambios necesarios en el patrón.
  • La diferencia entre una captura y una expresión constante puede ser difícil de detectar. Prueba a cambiar el 2 del segundo brazo por una variable y observa que no funciona. Cámbialo a const y verás que vuelve a funcionar.

Enumeraciones

Puntos clave:

  • La expresión if/else devuelve una enumeración que más tarde se descomprime con match.
  • Puedes probar a añadir una tercera variante a la definición de la enumeración y mostrar los errores al ejecutar el código. Señala los lugares en los que tu código está ahora incompleto y explica cómo el compilador intenta dar sugerencias.
  • The values in the enum variants can only be accessed after being pattern matched.
  • Demonstrate what happens when the search is inexhaustive. Note the advantage the Rust compiler provides by confirming when all cases are handled.
  • Guarda el resultado de divide_in_two en la variable result y hazlo coincidir mediante match en un bucle. No se compilará porque se utilizará msg cuando coincida. Para solucionarlo, haz coincidir &result en lugar de result. De esta forma, msg se convertirá en una referencia y no se utilizará. Esta "ergonomía de coincidencia" apareció en Rust 2018. Si quieres que sea compatible con las versiones anteriores de Rust, sustituye msg por ref msg en el patrón.