当向量中的每个项目都需要该向量中的所有其他项目时的所有权

Ownership when each item in a vector needs all the other items in said vector

我是 Rust 的新手,在这种情况下我无法弄清楚如何处理所有权(和生命周期?)。我不是编程新手,实际上我正在重新实现已经在 J​​S 中运行的东西 (https://sheraff.github.io/boids/)。


在这种情况下,Universe 基本上是一个包含许多 Entity 的“模拟”环境。在每个 universe.tick() 上,每个 Entity 都需要知道它可以“看到”哪个 Entity。为此,entity.update()Entity 的列表作为参数。

因此,我有这段脚本,但我似乎无法为它找到一个好的所有权结构:

for mut entity in self.entities {
    entity.update(&self.entities);
}

你会怎么做?

我可以告诉你我已经尝试过什么,但感觉我已经尝试了所有我能想到的,包括阅读 Rust 书,我已经收到了所有可能的错误消息...抱歉。


PS:当然,及时传递的不是完整的实体列表entity.update,而是过滤后的列表。


下面是代码结构的一般简化:

pub struct Entity {
    pub point: Point,
    vision: Cone,
    angle: Angle
}
impl Entity {
    pub fn update(&mut self, entities: &Vec<Entity>) {
        // ...
    }
}

pub struct Universe {
    pub entities: Vec<Entity>
}
impl Universe {
    pub fn new() -> Universe {
        let mut entities: Vec<Entity> = vec![];
        for _ in 1..200 {
            let mut entity = Entity::new();
            entities.push(entity);
        }

        Universe {
            entities
        }
    }

    pub fn tick(&self) {
        for mut entity in self.entities {
            entity.update(&self.entities);
        }
    }
}

如果每个实体都需要了解每个实体,那么似乎不是负责更新的实体。您可能应该从实体上的方法重构为对所有实体运行的函数。

在嵌套循环中迭代实体有点困难。一种解决方案是迭代数组的一个副本并允许另一个循环采用可变引用。

pub fn update_entities(entities: &mut Vec<Entity>) {
    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 循环打破了这一规则,因为您需要一个可变引用和一个不可变引用。