web-dev-qa-db-ja.com

Rustパラメーター化された関数でベクターをコピー/クローンする方法は何ですか?

不変のベクターを受け取り、それを複製またはコピーし、新しいベクターに何らかの処理を行い(シャッフルするなど)、新しい所有ベクターとして返すパラメーター化された関数を作成しようとしています。どのようにこれを行うことができ、それを行うための最も慣用的な方法は何ですか?

試行#1

pub fn shuffle<T>(vec: &mut [T]) {
    // ... contents removed: it shuffles the vector in place
    // ... so needs a mutable vector
}

pub fn shuffle_create_new<T: Clone>(vec: &[T]) -> Vec<T> {
    let mut newvec = vec.clone();
    shuffle(&mut newvec);
    return newvec.to_owned();
}

失敗する:

error[E0596]: cannot borrow immutable borrowed content as mutable
 --> src/main.rs:8:13
  |
8 |     shuffle(&mut newvec);
  |             ^^^^^^^^^^^ cannot borrow as mutable

newvecを可変と宣言しましたが。理由がわかりません。

試行#2

pub fn shuffle_owned<T: Clone>(mut vec: Vec<T>) -> Vec<T> {
    shuffle(&mut vec);
    return vec;
}

これはコンパイルしますが、私が望むことはしません。渡すベクトルshuffle_ownedは、関数にmovedを取得し、シャッフルし、所有者を呼び出し側に(戻り値を介して)転送します。したがって、元のベクトルはmodifiedです。

notが変更されるベクトルを渡す方法を知りたいが、値が新しいボックス化されたベクトルに複製され、終了時に返される-不変データを含む関数型プログラミング言語で行うように(Clojureなど)。

37
quux00

あなたの試み#1はほぼ正しいです。あなたはto_owned()を最初の行に移動するだけです:

fn shuffle<T>(vec: &mut [T]) {
    // ...
}

fn shuffle_create_new<T: Clone>(vec: &[T]) -> Vec<T> {
    let mut newvec = vec.to_vec();
    shuffle(&mut newvec);
    newvec
}

これは、スライスでclone()を呼び出すとスライス(つまり&[T])が返され、&[T]から&mut [T]に変更できないためです。参照(借用ポインター)。ただし、to_owned()を呼び出すと、Vec<T>の新しいインスタンスを取得し、それを可変変数に入れて可変ベクトルを取得できます。

Rust 1.0、 slice::to_vec またはToOwnedの-​​ to_owned() メソッドのいずれかtraitを使用して、Vec<T>から&[T]を作成できます。

&mut [T]からVec<T>を取得する方法もいくつかあります。スライス表記(&mut vec[..])、deref変換(&mut *vec)、または直接メソッド呼び出し(vec.as_mut_slice()、これは非推奨ですが)

21

これはおそらくあなたが望むものです:

pub fn copy_shuffle<T: Clone>(vec: &Vec<T>) -> Vec<T> {
    let mut vec = vec.clone();
    shuffle(&mut vec);
    vec
}

または

pub fn copy_shuffle<T: Clone>(vec: &[T]) -> Vec<T> {
    let mut vec = vec.to_vec();
    shuffle(&mut vec);
    vec
}
8
A.B.