#rust #ownership
#Ржавчина #владение
Вопрос:
Я очень новичок в Rust, и у меня возникают проблемы с пониманием того, как обрабатывать владение (и срок службы?) в этом случае. Я не новичок в программировании, и я фактически повторно внедряю то, что уже работает в JS (https://sheraff.&ithub.io/boids /).
В этом контексте Universe
это в основном среда «моделирования», содержащая множество Entity
. Для каждого из них universe.tick()
каждому Entity
необходимо знать, какой другой Entity
он может «видеть». Для этого entity.update()
принимает список Entity
в качестве аргумента.
В результате у меня есть этот фрагмент скрипта, для которого, похоже, я не могу найти хорошую структуру владения:
for mut entity in self.entities {
entity.update(amp;self.entities);
}
Как бы вы поступили по этому поводу?
Я мог бы рассказать вам, что я пробовал, но такое ощущение, что я перепробовал все, что мог придумать, включая чтение книги Rust, и у меня были все возможные сообщения об ошибках… Извините.
PS: конечно, со временем будет передан не весь список объектов entity.update
, а отфильтрованный список.
Ниже приведено общее упрощение структуры кода:
pub struct Entity {
pub point: Point,
vision: Cone,
an&le: An&le
}
impl Entity {
pub fn update(amp;mut self, entities: amp;Vec<Entity&&t;) {
// ...
}
}
pub struct Universe {
pub entities: Vec<Entity&&t;
}
impl Universe {
pub fn new() -&&t; Universe {
let mut entities: Vec<Entity&&t; = vec![];
for _ in 1..200 {
let mut entity = Entity::new();
entities.push(entity);
}
Universe {
entities
}
}
pub fn tick(amp;self) {
for mut entity in self.entities {
entity.update(amp;self.entities);
}
}
}
Комментарии:
1. Это может помочь понять «владение rust» youtu.be/TCUBSbJENO4
2. @nbari спасибо, это было действительно очень хорошо. Но это не вошло в заимствования (хотя другие их видео, похоже, делают), которые кажутся решающими для проблемы в этом посте.
Ответ №1:
Если каждой сущности нужно знать о каждой сущности, то кажется, что это не та сущность, которая отвечает за обновление. Вероятно, вам следует провести рефакторинг от метода объекта к функции, которая работает со всеми объектами.
Перебор объектов во вложенном цикле немного затруднен. Одним из решений было бы выполнить итерацию по одной копии массива и разрешить другому циклу принимать изменяемую ссылку.
pub fn update_entities(entities: amp;mut Vec<Entity&&t;) {
for a in entities.clone() {
for mut entity in entities.iter_mut() {
if entity.id == a.id { // If you can compare them, otherwise use indexed for loop and compare indices.
continue;
}
// Do stuff.
}
}
}
Причина, по которой вам нужно копировать, заключается в золотом правиле Rust: у вас может быть либо одна изменяемая ссылка любое количество неизменяемых ссылок.,,,,, Вложенные циклы for нарушают это правило, потому что вам нужна одна изменяемая ссылка и одна неизменяемая.
Комментарии:
1. Значит, в Rust никогда не бывает вложенных циклов? Кроме w / clonin&?
2. @Sheraff Я не знаю ни одного хорошего, чистого способа сделать это. Хотя вместо копирования вы могли бы сделать функцию полностью чистой (как определено в функциональном программировании; без изменяемого состояния и побочных эффектов) и возвращать новый массив объектов из неизменяемого ввода. Вероятно, это то, что я бы сделал, но это зависит от того, что вы на самом деле делаете в своем обновлении.