Rust 使用可变迭代器进行迭代时对不可变借用执行操作
下面是一个简单的人工示例来说明问题:Rust 使用可变迭代器进行迭代时对不可变借用执行操作,rust,ownership,Rust,Ownership,下面是一个简单的人工示例来说明问题: fn sum_slice(v: &[i32]) -> i32 { v.iter().sum() } fn sum_previous(v: &mut [i32]) { for (i, val) in v.iter_mut().enumerate() { *val = sum_slice(&v[0..i]); } } fn main() { let mut v = vec![1,1
fn sum_slice(v: &[i32]) -> i32 {
v.iter().sum()
}
fn sum_previous(v: &mut [i32]) {
for (i, val) in v.iter_mut().enumerate() {
*val = sum_slice(&v[0..i]);
}
}
fn main() {
let mut v = vec![1,1,1,1,1,1,1];
sum_previous(&mut v);
println!("{:?}", v);
}
理想情况下,目的是sum\u previous
将获取提供的切片,并将每个元素替换为先前元素的总和
但这会产生错误:
error[E0502]:无法将“*v”作为不可变项借用,因为它也是作为不可变项借用的
易变的
-->src/main.rs:7:27
|
6 |对于v.iter_mut()中的(i,val)枚举(){
| ------------------------
| |
|可变借用发生在这里
|可变借用后来在这里使用
7 |*val=sum_切片(&v[0..i]);
|^此处发生不可变借用
我理解Rust限制我们只拥有一个可变参考,而不是同时拥有不变参考的问题。我也可以提出不同的解决方案,比如使用另一个向量来存储结果,但问题不是如何解决它,而是这里可以接受的模式是什么
FWIW最初的问题是细胞自动机的实现,其中要处理的网格和要根据其邻居更新的每个单元。在这种情况下,网格是可变借用的,而计算更新的函数需要一个不可变的引用。您可以使用:
fn sum_previous(v:&mut[i32]){
对于1..v.len()中的i{
let(头、尾)=v.在(i)处分开;
尾[0]=和片(头);
}
}
()谢谢,这对我来说是一个有趣的发现,它为人工示例提供了一种解决方案,但我不确定它如何解决一般问题。假设我们使用的不是切片,而是一些
结构,其中一个方法将采用&mut self
,并将尝试执行另一个采用不可变的方法&self
@EugeneSh。这不是问题,因为在结构上有&mut
,也允许调用需要对它进行不可变引用的方法和函数()。这个问题只在处理迭代器时才会发生,而且总是有办法解决的。@EugeneSh。我不认为有“一般问题”但是许多不同的方法…它们看起来很相似,但最终却有不同的解决方案。在&mut方法调用另一个方法的示例中:您可以借用您的“&mut self”作为“&self”所以没有问题——只有当你同时需要两个引用时问题才会存在。@JussiKukkonen我可以给你看一下最初的问题吗?看起来我确实同时需要两个引用。。是的。如果你认为我问题中的例子不具代表性,我可能需要编辑它。@EugeneSh。这是康威的l游戏的一个变体ife-你确定你应该在原地修改权重吗?如中所述,你确定正在更新的邻居应该使用部分更新的网格立即触发更新吗?我不认为是这样;我不知道有哪一个细胞自动机可以这样工作。另外,这也建议使用索引。你使用的是我已经支持&v[0..i]
;实际上没有任何理由喜欢*val
而不是v[i]
。事实上,我认为一致使用索引比将索引与迭代混合使用更具可读性。@trentcl谢谢,这是一个很好的复制品-正好反映了我最初的问题