首页 > 解决方案 > 使用可变迭代器进行迭代时对不可变借用执行操作

问题描述

这是一个简单的人工示例来说明问题:

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_previous获取提供的切片并将每个元素替换为先前元素的总和。

但这会产生错误:

    error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as 
    mutable

    --> src/main.rs:7:27
      |
    6 |     for (i, val) in v.iter_mut().enumerate() {
      |                     ------------------------
      |                     |
      |                     mutable borrow occurs here
      |                     mutable borrow later used here
    7 |         *val = sum_slice(&v[0..i]);
      |                           ^ immutable borrow occurs here

Rust 游乐场链接

我理解 Rust 限制我们同时拥有一个可变引用和不可变引用的问题。我也可以提供不同的解决方案,例如使用另一个向量来存储结果,但问题不是如何解决它,而是这里可以接受的模式是什么?

FWIW 最初的问题是元胞自动机的实现,其中要处理一个网格,并且每个单元都要根据其邻居进行更新。在这种情况下,网格是可变借用的,而计算更新的函数需要一个不可变的引用。

标签: rustownership

解决方案


您可以使用以下方法执行此操作split_at_mut

fn sum_previous(v: &mut [i32]) {
    for i in 1..v.len() {
        let (head, tail) = v.split_at_mut(i);
        tail[0] = sum_slice(head);
    }
}

永久链接到操场


推荐阅读