【问题标题】:Ownership when each item in a vector needs all the other items in said vector当向量中的每个项目需要所述向量中的所有其他项目时的所有权
【发布时间】:2020-08-08 19:16:19
【问题描述】:

我对 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);
        }
    }
}

【问题讨论】:

  • 这可能有助于理解“锈所有权”youtu.be/TCUBSbJENO4
  • @nbari 谢谢你,确实不错。但它并没有借用(尽管他们的其他视频似乎这样做),这似乎对这篇文章中的问题至关重要。

标签: rust ownership


【解决方案1】:

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

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

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 循环打破这条规则,因为你需要一个可变引用和一个不可变引用。

【讨论】:

  • 那么 Rust 中从来没有任何嵌套循环吗?除了克隆?
  • @Sheraff 我不知道有什么好的、干净的方法。虽然,而不是复制,您可以使函数完全纯净(如函数式编程中定义的那样;没有可变状态和副作用)并从不可变输入返回一个新的实体数组。我可能会这样做,但这取决于您在更新中实际执行的操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
相关资源
最近更新 更多