1.7 Un lugar donde guardarlas
Esta traducción fue asistida por IA y revisada superficialmente. Si encuentras errores o algo no suena natural, escríbeme — lo agradezco.
Una pieza no necesita almacenamiento - simplemente está ahí, en la mano, en el banco, cerca. Una segunda pieza exige una decisión: dónde poner la primera. Una tercera exige una política. Un artesano que sabe forjar una pieza pero no ha resuelto dónde ponerla empieza desde una mesa vacía cada vez. A veces esto se llama proceso. Más a menudo, problema.
Lo que necesitas
Hasta ahora el trabajo involucraba una única tarea, y todo era sencillo. Pero dos tareas ya
exigen un sistema de nombres: task1, task2. Con diez, ese enfoque se vuelve incómodo, y
si el número de tareas no se conoce de antemano - se vuelve imposible.
Se necesita un contenedor: un lugar donde poner tareas y recuperarlas cuando llegue el
momento. En Rust, una lista de elementos del mismo tipo usa Vec. Vec<Task> es una lista
de tareas; los corchetes angulares le dicen al compilador que en este contenedor solo entran
valores de tipo Task. Los corchetes angulares volverán a aparecer en el capítulo 3.4 - por
ahora, lee Vec<Task> como “una lista de tareas.”
Con un contenedor importan dos operaciones: meter y sacar.
La construcción
Crea la lista e intenta añadir una tarea de inmediato:
let tasks = Vec::new();
tasks.push(Task::new(1, "Buy coffee"));
El compilador, como de costumbre, tiene algo que decir:
error[E0596]: cannot borrow `tasks` as mutable, as it is not declared as mutable
--> src/main.rs:XX:XX
|
XX | let tasks = Vec::new();
| ----- help: consider changing this to be mutable: `mut tasks`
XX | tasks.push(Task::new(1, "Buy coffee"));
| ^^^^^^^^^^^ cannot borrow as mutable
La misma situación que con complete en el capítulo 1.6: la modificación requiere mut.
push cambia la lista - debe declararse mutable:
let mut tasks: Vec<Task> = Vec::new();
Añade la primera tarea:
tasks.push(Task::new(1, "Buy coffee"));
Ahora intenta recuperarla en una variable y trabajar con ella como antes:
let mut task = tasks[0];
El compilador recuerda:
error[E0507]: cannot move out of index of `Vec<Task>`
|
| let mut task = tasks[0];
| ^^^^^^^^ move occurs because value has type `Task`,
| which does not implement the `Copy` trait
Sacar una tarea de la lista no está permitido - dejaría un hueco. tasks[0] no es una
variable separada sino una posición dentro del Vec. Para trabajar con ella, se necesita
una referencia:
let task = &mut tasks[0];
&mut tasks[0] es una referencia mutable al primer elemento dentro de la lista. La tarea
permanece en el Vec; task es solo la forma de acceder a ella. La API conocida funciona
a través de ella:
println!("#{}: {}", task.id, task.title);
task.complete();
if task.is_done() {
println!("Task 1 done");
}
Meter y sacar - confirmado. Añade el resto:
tasks.push(Task::new(2, "Buy milk"));
tasks.push(Task::new(3, "Buy eggs"));
push añade al final de la lista - si quieres experimentar, milk está en el índice 1
y eggs en el 2.
El resultado
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"));
}
#1: Buy coffee
Task 1 done
make ci pasa. Vec almacena las tareas; push las añade, &mut tasks[0] recupera una y
permite trabajar con ella en su lugar.
El código completo de
tqpara este capítulo está en1-a-task/07-a-place-to-keep-them/.
Scroll: Tus datos no están donde crees Scroll: El borrow checker tiene una regla - y no es la que crees