Desestructurar

A continuación se presentan algunos aspectos adicionales sobre cómo desestructurar los valores de un struct o enum. Ya se vio que se podía realizar mediante let y el uso de variables que recuperan parte o todo el contenido de la estructura o enumerado. De esta forma, se tienen los valores de forma separada. Se puede observar en el siguiente ejemplo:

struct Persona { // crea una estructura simple para Persona
    nombre: String,
    real_nombre: String,
    altura: u8,
    felicidad: bool
}

fn main() {
    let papa_doc = Persona { // se crea la variable papa_doc
        nombre: "Papa Doc".to_string(),
        real_nombre: "Clarence".to_string(),
        altura: 170,
        felicidad: false
    };

    let Persona { // Se "desestructura" a  papa_doc
        nombre: a,
        real_nombre: b,
        altura: c,
        felicidad: d
    } = papa_doc;

    println!("Lo llaman {} pero su nombre real es {}. Es {} cm de alto y ¿es feliz? {}", a, b, c, d);
}

Que imprime: Lo llaman Papa Doc pero su nombre real es Clarence. Es 170 cm de alto y ¿es feliz? false

Primero se crea la estructura let papa_doc = Persona { campos }. Luego, de forma simétrica, se escribe let Persona { campos } = papa_doc para desestructurarla.

No es necesario escribir nombre: a - se puede escribir solo nombre. Pero aquí se escribe nombre: a porque se quiere usar este valor de forma independiente mediante la variable a.

A continuación se presenta un ejemplo más amplio. En este ejemplo, se usa la estructura Ciudad. Se utiliza una función asociada new para crear ciudades. Posteriormente, se utiliza la función procesar_valores_ciudad para hacer cosas con sus valores. En la función, se crea un Vec, pero se pueden imaginar muchas más operaciones sobre estos datos después de desestructurarlos.

struct Ciudad {
    nombre: String,
    nombre_antes: String,
    poblacion: u32,
    fecha_fundacion: u32,
}

impl Ciudad {
    fn new(nombre: String, nombre_antes: String, poblacion: u32, fecha_fundacion: u32) -> Self {
        Self {
            nombre,
            nombre_antes,
            poblacion,
            fecha_fundacion,
        }
    }
}

fn procesar_valores_ciudad(ciudad: &Ciudad) {
    let Ciudad {
        nombre,
        nombre_antes,
        ..
    } = ciudad;
        // se dispone de los valores separados
    let dos_nombres = vec![nombre, nombre_antes];
    println!("Los dos nombres de la ciudad son {:?}", dos_nombres);
}

fn main() {
    let tallinn = Ciudad::new("Tallinn".to_string(), "Reval".to_string(), 426_538, 1219);
    procesar_valores_ciudad(&tallinn);
}

El código anterior imprime Los dos nombres de la ciudad son ["Tallinn", "Reval"].