2016-01-06 4 views
0

Я делаю некоторые изменения проблемы dining philosophers из книги Руста.Использование элемента списка для редактирования списка

В книге они создают всех философов вручную, при этом последний имеет свою левую и правую руку. Я сделал это программно (используя цикл for, к которому я подтолкнул философов), и теперь я хочу изменить окончательного философа.

Это то, что я хочу сделать

// make the last philosopher left handed (switch forks) 
let p = &philosophers[length - 1]; 
philosophers[length - 1] = Philosopher{left: p.right, right: p.left, name: p.name.clone()}; 
// error: cannot move out of indexed content [E0507] 

Это то, что я должен сделать

philosophers[length - 1] = Philosopher{ 
    left: philosophers[length - 1].right, 
    right: philosophers[length - 1].left, 
    name: philosophers[length -1].name.clone(), 
}; 

Первый пример не компилируется, и я не могу найти способ получить его скомпилировать, не делая что-то вроде let p = philosophers[length - 1].clone() - который полностью копирует данные! (не совсем то, что я хочу).

Есть ли способ сделать это более ржаво?

+1

Я пошел вперед и удалил ответ с вопроса; если я удалю некоторый контент, который вы хотите получить (например, чтобы опубликовать свой собственный ответ, если вы думаете, что ваш код лучше, чем Lukas), вы можете нажать «отредактированный X время назад», который ссылается на страницу [ревизий] https://stackoverflow.com/posts/34627695/revisions) для вашего вопроса и захватить все, что от вас требуется. –

ответ

3

Действительно, вы не можете изменить то, что вы сейчас заимствуете. Вы можете клонировать его - вы уже клонируете поле name и left и right только usize.

Предполагая, что ваша структура содержит все больше и больше данных, клонирование - это не вариант. В этом случае существует несколько возможных решений. Вы можете использовать Vec вместо обычного массива: сначала создайте всех 4 нормальных философов, а затем push последний. Или вы можете использовать std::mem::swap поменять left и right:

std::mem::swap(&mut philosophers[length - 1].left, &mut philosophers[length - 1].right); 
+0

Ошибка Gettin: не может брать неизменяемое поле «p.left» как изменчивое ». Как сделать элемент в списке изменчивым? Мое текущее объявление - 'let mut philosophers: Vec = vec! [];'. Попытка поставить 'mut' в разных местах, похоже, не решила мою проблему. – vitiral

+0

Теперь все работает благодаря вашему редактированию. Благодаря тонну! – vitiral

0

Этот пример настолько коротка, что ИМХО оригинальное решение (без петли) более выразительным. Но если вы хотите изменить последний философ, вы можете сделать это:

let p = &mut philosophers[length - 1]; 
let left = p.left; 
let right = p.right; 
p.left = right; 
p.right = left; 

Вы будете работать на ссылках последнего философа непосредственно. Таким образом, вам не нужно клонировать его/ее имя, просто поменяйте местами вилки.

+0

это также скопирует данные. Я пытался понять ржавый способ сделать это, не копируя данные. Очевидно, что в этом простом примере копирование нескольких uint не является проблемой :) – vitiral

Смежные вопросы