7

ベクトルの最後の要素を取得し、それを使用して次にプッシュする要素を決定したいと思います。これが機能しない例を次に示しますが、私が達成しようとしていることを示しています。

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

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

pushベクトルも不変に借用されている間は使用できません:

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

これを行うにはどうすればよいでしょうか。

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 に答える