7

I would like to get the last element of a vector and use it to determine the next element to push in. Here's an example how it doesn't work, but it shows what I'm trying to achieve:

let mut vector: Vec<i32> = Vec::new();

if let Some(last_value) = vector.last() {
    vector.push(*last_value + 1);
}

I can't use push while the vector is also borrowed immutably:

error[E0502]: cannot borrow `vector` as mutable because it is also borrowed as immutable
 --> src/main.rs:5:9
  |
4 |     if let Some(last_value) = vector.last() {
  |                               ------ immutable borrow occurs here
5 |         vector.push(*last_value + 1);
  |         ^^^^^^ mutable borrow occurs here
6 |     }
  |     - immutable borrow ends here

What would be a good way to do this?

4

1 回答 1

9

在非词汇生命周期之后

您的原始代码在 Rust 2018 中按原样工作,它启用了non-lexical-lifetimes

fn main() {
    let mut vector: Vec<i32> = Vec::new();

    if let Some(last_value) = vector.last() {
        vector.push(*last_value + 1);
    }
}

借用检查器已得到改进,以实现引用last_value不与vector推入新值所需的可变借用重叠。

请参阅从 HashMap 或 Vec 返回引用导致借用持续超出其所在范围?对于借用检查器还不够聪明来处理的类似情况(从 Rust 1.32 开始)。

在非词汇生命周期之前

结果vector.last()是一个Option<&i32>. 该值中的引用保留了借用的向量。我们需要先删除对向量的所有引用,然后才能推送到它。

如果您的向量包含Copy可用值,请将值从向量中复制出来以更快地结束借用。

fn main() {
    let mut vector: Vec<i32> = Vec::new();

    if let Some(&last_value) = vector.last() {
        vector.push(last_value + 1);
    }
}

在这里,我使用了模式Some(&last_value)而不是Some(last_value). 这会破坏引用并强制复制。如果您使用无法使用的类型尝试此模式Copy,您将收到编译器错误:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:4:17
  |
4 |     if let Some(&last_value) = vector.last() {
  |                 ^----------
  |                 ||
  |                 |hint: to prevent move, use `ref last_value` or `ref mut last_value`
  |                 cannot move out of borrowed content

如果您的向量不包含Copy可用的类型,您可能需要先克隆该值:

fn main() {
    let mut vector: Vec<String> = Vec::new();

    if let Some(last_value) = vector.last().cloned() {
        vector.push(last_value + "abc");
    }
}

或者您可以以另一种方式转换该值,以便.map()调用返回一个不从向量借用的值。

fn main() {
    let mut vector: Vec<String> = Vec::new();

    if let Some(last_value) = vector.last().map(|v| v.len().to_string()) {
        vector.push(last_value);
    }
}
于 2015-10-27T03:32:38.240 回答