如何处理相互依赖的Rust借用?

时间:2018-03-23 01:08:19

标签: rust

我在Rust中写了一个像Rogue一样的东西。我的Player Vec盒装TimedEffects。定时效果包含activate(&mut Player)deactivate(&mut Player)方法,以及减少剩余时间的tick()方法。当它变为零时,应该调用deactivate()方法。

pub struct Player {
    timed_effects: Vec<Box<TimedEffect>>,
}

每次玩家移动时,我都需要减少剩余的时间。这是在Player方法内完成的:

impl Player {
    fn regenerate(&mut self) {
        self.timed_effects.iter_mut().for_each(|te| te.tick());

        for i in 0..self.timed_effects.len() {
            if self.timed_effects[i].ticks_remaining() == 0 {
                let bte = self.timed_effects.swap_remove(i);
                bte.deactivate(self);
            }
        }
    }
}

我最初尝试将self参数(&mut Player)传递给tick()对象的TimedEffect方法,并使用逻辑自动调用deactivate(player)时间变为零。

迭代向量构成了对(Playerself的借用,这与将&mut Player参数传递给tick()不兼容,甚至与单独的迭代无关.filter

相反,如图所示,我发现自己迭代一系列整数,将向量中的框提取为局部变量,然后在其上调用.deactivate(self)

这很痛苦。

鉴于效果需要与受害者建立联系,因此deactivate()方法可以撤消效果,我应该如何构建这些对象,以便我不会在这个依赖借用网络中纠结?

1 个答案:

答案 0 :(得分:2)

为避免借用问题,您可以分两步完成:

  1. 将从timed_effects完成的效果传输到缓冲区
  2. 遍历缓冲区并调用deactivate
  3. 我会使用夜间Vec::drain_filter来获取更加流畅的代码,但它肯定不是强制性的。

    fn regenerate(&mut self) {
        self.timed_effects.iter_mut().for_each(|te| te.tick());
    
        let timed_out: Vec<_> =
            self.timed_effects
                .drain_filter(|t| t.ticks_remaining() == 0)
                .collect();
    
        //  Split iteration in a second step to stop borrowing self.
        for timer in timed_out {
            timer.deactivate(self);
        }
    }
    

    为了进一步提高效率,您可以将可重用缓冲区传递给regenerate(以避免分配)。

相关问题