Problema con iterador en Rust

Publicado por Brisa
hace 8 meses

Hola a todos,

Estoy teniendo un problema con un iterador en Rust y me gustaría saber si alguien puede ayudarme a resolverlo. Estoy trabajando en un proyecto y necesito iterar sobre un vector utilizando un bucle for. Sin embargo, estoy obteniendo un error que no entiendo.

Aquí está el código que estoy utilizando:

fn main() {

    let numbers = vec![1, 2, 3, 4, 5];

    for number in numbers.iter() {
        println!("Number: {}", number);
        numbers.push(number + 1);
    }
}

Al ejecutar este código, obtengo el siguiente mensaje de error:

error[E0596]: cannot borrow `numbers` as mutable, as it is not declared as mutable
 --> main.rs:7:9
  |
3 |     let numbers = vec![1, 2, 3, 4, 5];
  |         ------ consider changing this to `mut numbers`
...
7 |         numbers.push(number + 1);
  |         ^^^^^^^ cannot borrow as mutable

No entiendo por qué obtengo este error, ya que estoy utilizando el método iter() para obtener un iterador inmutable sobre el vector. ¿Alguien puede explicarme qué estoy haciendo mal y cómo solucionarlo?

¡Gracias de antemano!

Rust Iterador Vec
Respuesta de Gordon Shumway
hace 8 meses

¡Hola Brisa! El error que estás obteniendo es porque estás intentando modificar el vector numbers al mismo tiempo que estás iterando sobre él. En Rust, esto no está permitido porque podría causar condiciones de carrera y otros problemas de seguridad en acceso a memoria. Aquí te explico un poco más y cómo podrías solucionarlo.

Primero, el error te indica que no puedes tomar prestado numbers como mutable (con capacidad de cambiar su contenido) porque no lo has declarado como mutable. En Rust, todas las variables son inmutables por defecto; tienes que añadir mut para cambiar eso.

Para corregir el primer error, necesitas declarar numbers como mutable:

let mut numbers = vec![1, 2, 3, 4, 5];

Pero incluso haciendo numbers mutable, iterar y modificar la colección al mismo tiempo no se permite por las razones que ya mencioné. Para resolver esto, puedes hacerlo de varias maneras, pero una solución común es recolectar los elementos que quieres añadir en un nuevo vector y combinar ambos vectores después. Aquí hay un ejemplo de cómo podrías hacerlo:

fn main() {
    let mut numbers = vec![1, 2, 3, 4, 5];
    let mut to_add = Vec::new(); // Un nuevo vector para guardar los números a agregar

    for &number in numbers.iter() {
        println!("Number: {}", number);
        to_add.push(number + 1); // Añadir al vector nuevo, así no modificas `numbers` durante la iteración
    }

    numbers.extend(to_add); // Extendemos `numbers` con los elementos de `to_add`
    println!("{:?}", numbers);
}

Este código primero crea un vector adicional to_add donde almacena los nuevos elementos. Una vez finalizada la iteración, extiende el vector original numbers con los nuevos elementos de to_add. Además, &number en la línea de iteración se usa para desreferenciar el valor que devuelve iter(), así se obtiene directamente el número y no una referencia a él.

¡Espero haber aclarado tus dudas y ayudarte a seguir con tu proyecto en Rust!