El shadowing (ensombrecimiento) es una técnica en Rust que permite declarar una nueva variable con el mismo nombre que una variable anterior dentro de un mismo ámbito. Esto se logra utilizando la palabra clave let nuevamente. A diferencia de la mutabilidad (mut), donde modificas el valor de una posición de memoria existente, el shadowing crea una nueva variable que “oculta” a la anterior.

Esta técnica es extremadamente útil cuando necesitas transformar un valor pero no quieres crear nombres de variables cada vez más descriptivos o confusos, como texto_limpio, texto_parseado, texto_final. Con el shadowing, puedes reutilizar el nombre original para mantener el código limpio. La diferencia fundamental con mut es que, al crear una nueva variable, puedes cambiar el tipo de dato. Con mut, el tipo de la variable debe permanecer constante durante toda su vida.

Sin embargo, debe usarse con moderación. Si sombreas una variable que aún necesitas en el mismo bloque de código, perderás el acceso a la original, lo que puede generar errores de lógica.

fn main() {
    // 1. Shadowing para cambiar de tipo (muy común al parsear)
    let espacio = "   "; // Tipo: &str
    let espacio = espacio.len(); // Tipo: usize (el nombre se reutiliza)

    // 2. Shadowing para transformaciones de datos
    let mensaje = "Hola Rust";
    let mensaje = format!("El mensaje es: {}", mensaje); // Tipo: String

    // 3. Shadowing en ámbitos (scopes) anidados
    let x = 10; // Variable original
    {
        let x = x * 2; // Nueva 'x' que solo vive en este bloque
        println!("Dentro del bloque (sombreada): x = {}", x);
    } // Aquí la 'x' sombreada desaparece de la memoria

    println!("Fuera del bloque (original): x = {}", x);
    println!("Longitud del espacio: {}", espacio);
    println!("Mensaje transformado: {}", mensaje);
}

Análisis del código

  • espacio: En la primera línea, espacio es de tipo &str (una cadena de texto). En la siguiente línea, usamos let de nuevo para declarar una nueva variable llamada espacio, pero ahora su tipo es usize (un entero) que contiene la longitud de la cadena original. Esto no habría sido posible con mut.
  • mensaje: Primero se define como una cadena de texto estática (&str). Luego, mediante shadowing, se redefine como un objeto String dinámico usando la macro format!. Esto permite procesar la variable sin inventar un nombre nuevo como mensaje_string.
  • x: Este es el ejemplo clásico de scope. La variable x original tiene el valor 10. Al entrar en el bloque { ... }, se crea una nueva x que multiplica el valor por 2. Esta x interna “ensombrece” a la externa, pero solo dentro de las llaves.
  • Ámbito de visibilidad: Una vez que el programa sale del bloque de la x sombreada, la variable x original (con valor 10) vuelve a estar disponible, demostrando que el shadowing es controlado por el alcance del compilador.

11