← Оглавление

1.9 В деле

Полка есть. Задачи на ней стоят ровно. Но каждый раз, когда нужно добавить или просмотреть - мастер тянется к полке напрямую, руками, без инструмента. Пока всё помещается в один взгляд - терпимо. Это и называется “пока”.

Попытка

main сейчас сама кладёт задачи в список - напрямую, через push. Пока задач три и их добавление - единственная операция, push не мозолит глаза. Пора дать этому имя: функция add принимает список и задачу, кладёт задачу в список. Список отдавать не нужно - достаточно ссылки:

fn add(tasks: &Vec<Task>, task: Task) {
    tasks.push(task);
}

Компилятор подсказывает:

error[E0596]: cannot borrow `*tasks` as mutable, as it is behind a `&` reference
 --> src/main.rs:XX:XX
  |
XX |     tasks.push(task);
  |     ^^^^^ `tasks` is a `&` reference, so the data it refers to cannot be borrowed as mutable

Что знает компилятор

&Vec<Task> - ссылка на чтение. Через неё нельзя изменить то, на что она указывает. push добавляет элемент - это изменение. Компилятор это видит.

В главе 1.5 та же ситуация решалась добавлением mut: task_complete принимала &mut Task, а не &Task. Здесь принцип тот же - получатель другой:

fn add(tasks: &mut Vec<Task>, task: Task) {
    tasks.push(task);
}

&mut Vec<Task> - изменяемая ссылка: функция меняет список, не захватывая его.

Заклинание

fn main() {
    let mut tasks: Vec<Task> = Vec::new();

    add(&mut tasks, Task::new(1, "Buy coffee"));
    add(&mut tasks, Task::new(2, "Buy milk"));
    add(&mut tasks, Task::new(3, "Buy eggs"));

    let task = &mut tasks[0];
    task.complete();

    if task.is_done() {
        println!("Task 1 done");
    }

    for task in &tasks {
        println!("#{}: {} - {:?}", task.id, task.title, task.status);
    }
}
Task 1 done
#1: Buy coffee - Done
#2: Buy milk - Todo
#3: Buy eggs - Todo

make ci проходит. У add есть имя - список больше не заполняется руками.

Полный код tq для этой главы - 1-a-task/09-the-list-at-work/.