Владение, когда каждому элементу в векторе требуются все остальные элементы в указанном векторе

#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 Я не знаю ни одного хорошего, чистого способа сделать это. Хотя вместо копирования вы могли бы сделать функцию полностью чистой (как определено в функциональном программировании; без изменяемого состояния и побочных эффектов) и возвращать новый массив объектов из неизменяемого ввода. Вероятно, это то, что я бы сделал, но это зависит от того, что вы на самом деле делаете в своем обновлении.