1.8 El inventario
Esta traducción fue asistida por IA y revisada superficialmente. Si encuentras errores o algo no suena natural, escríbeme — lo agradezco.
En teoría, si sabes el número exacto de tareas en la lista y recuerdas que el conteo empieza en cero, un bucle es innecesario. En la práctica, ambas condiciones se rompen más rápido de lo esperado. Especialmente la segunda.
El intento
La lista de tareas ya está formada. El siguiente paso natural es recorrerla y verlo todo de una vez antes de añadir algo nuevo. Rust tiene una construcción conveniente para esto:
for task in tasks {
println!("#{}: {} - {:?}", task.id, task.title, task.status);
}
tasks.push(Task::new(2, "Buy milk"));
for ... in es un bucle: toma elementos de una colección uno por uno y ejecuta el cuerpo
(dentro de las llaves) para cada uno. Parece correcto. Pero el compilador tiene una nota:
error[E0382]: borrow of moved value: `tasks`
|
| let mut tasks: Vec<Task> = Vec::new();
| --------- move occurs because `tasks` has type `Vec<Task>`,
| which does not implement the `Copy` trait
| for task in tasks {
| ----- `tasks` moved due to this implicit call to `.into_iter()`
| tasks.push(Task::new(2, "Buy milk"));
| ^^^^^ value borrowed here after move
Lo que sabe el compilador
for task in tasks es un move. El bucle toma tasks entero y se convierte en su
propietario. Cuando el bucle termina, la colección se destruye con él. La línea con push
busca algo que ya no existe.
El mismo patrón apareció en el capítulo 1.5: pasar es ceder. Aquí el receptor no es una función sino un bucle.
La corrección es la misma: pasar el derecho a leer, no la propiedad:
for task in &tasks {
println!("{:?}", task);
}
&tasks es una referencia a la colección. El bucle lee a través de ella; tasks sigue
viviendo en main.
El conjuro
fn main() {
let mut tasks: Vec<Task> = Vec::new();
tasks.push(Task::new(1, "Buy coffee"));
let task = &mut tasks[0];
println!("#{}: {}", task.id, task.title);
task.complete();
if task.is_done() {
println!("Task 1 done");
}
tasks.push(Task::new(2, "Buy milk"));
tasks.push(Task::new(3, "Buy eggs"));
for task in &tasks {
println!("{:?}", task);
}
}
#1: Buy coffee
Task 1 done
Task { id: 1, title: "Buy coffee", status: Done }
Task { id: 2, title: "Buy milk", status: Todo }
Task { id: 3, title: "Buy eggs", status: Todo }
make ci pasa. Toda la colección puede revisarse ahora en un solo recorrido.
El código completo de
tqpara este capítulo está en1-a-task/08-the-inventory/.