我有一些结构:
struct data {
payload: i32,
}
struct bar {
datas: Vec<data>,
}
impl bar {
pub fn f2(&self, dta: &mut data) {
dta.payload = 1;
}
pub fn f1(&mut self) {
let zeroes = self.datas.iter_mut().filter(|b| b.payload == 0);
for zero in zeroes {
self.f2(zero);
}
}
}
当我尝试编译它时,编译器会抱怨:
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/lib.rs:17:13
|
15 | let zeroes = self.datas.iter_mut().filter(|b| b.payload == 0);
| ---------- mutable borrow occurs here
16 | for zero in zeroes {
| ------ mutable borrow later used here
17 | self.f2(zero);
| ^^^^ immutable borrow occurs here
我明白了为什么编译器不允许我这样做;错误消息是非常好的。有没有做这种事情的好方法而编译器不会抱怨呢?这种行为会阻止某些我认为会有所帮助的代码结构形式,例如将给定成员struct实例的处理传递给另一个函数-上面的例子很简单,我们可以轻松地就地修改每个给定的“零”实例,但是,如果f2
包含复杂的逻辑,则可能会使f1
中的代码。我知道,在这种情况下,也可以使用关联的函数,但是再说一次:此示例已简化,如果f2需要对该结构的其他字段进行读取访问,则关联的函数将不起作用。
到目前为止,我提出的一种解决方案是不使用迭代器,而是使用带数据结构副本的for循环:
pub fn f1(&mut self) {
for i in 0..self.datas.len() {
if self.datas[i].payload == 0 {
let mut d0 = *self.datas.get_mut(i).unwrap();
self.f2(&mut d0);
}
}
}
虽然这可以在某些地方使用(甚至可能实际上与迭代器一起使用),但还是有点失误了,因为d0
现在是一个副本,这意味着必须将d0
复制回来进入self.datas
。同样,这个“解决方案”要求我们实现Copy
特性,这对于复杂的结构可能是乏味的(..并且在运行时很昂贵)。
正确的方法是什么?