根据其他内部字段改变 Rc Refcell 的字段

Mutating fields of Rc Refcell depending on its other internal fields

我需要迭代 Rc RefCell 中结构的一个字段,并根据它的其他字段修改它的一些参数。 例如对于结构 Foo:

pub struct Foo {
    pub foo1: Vec<bool>,
    pub foo2: Vec<i32>,
}

以下代码出现混乱:

fn main() {
    let foo_cell = Rc::new(RefCell::new(Foo { foo1: vec![true, false], foo2: vec![1, 2] }));
    foo_cell.borrow_mut().foo2.iter_mut().enumerate().for_each(|(idx, foo2)| {
        if foo_cell.borrow().foo1[idx] {
            *foo2 *= -1;
        }
    });
}

我可以通过在可变借用之前克隆 foo1 并仅在闭包内使用克隆来解决它,但这会导致不必要的复制。事实上,我基本上需要一个对 foo2 的可变引用和一个对 foo1 的不可变引用(请注意这是简化的代码,在这里不会压缩迭代器)。我知道代码不符合借用规则。有没有办法在不克隆数据的情况下让它工作?

问题是您试图在每个循环迭代中重新借用 RefCell,而它已经被借用以使迭代器超过 foo2。解决方案是在循环之前使用单个 foo_cell.borrow_mut() 并分别借用 foo1foo2.

请注意,需要取消对 foo_cell.borrow_mut() 的引用才能完成这项工作。

use std::rc::Rc;
use std::cell::RefCell;

pub struct Foo {
    pub foo1: Vec<bool>,
    pub foo2: Vec<i32>,
}
fn main() {
    let foo_cell = Rc::new(RefCell::new(Foo {
        foo1: vec![true, false],
        foo2: vec![1, 2]
        
    }));
    // The dereference is required to get &mut Foo out of the RefMut<Foo>
    let borrow = &mut *foo_cell.borrow_mut();
    let foo1 = &borrow.foo1;

    borrow.foo2.iter_mut().enumerate().for_each(|(idx, foo2)| {
        if foo1[idx] {
            *foo2 *= -1;
        }
    });
}

Playground