Подтвердить что ты не робот

Что такое идиоматический способ ржавчины для копирования/клонирования вектора в параметризованной функции?

Я пытаюсь написать параметризованную функцию, которая берет неизменный вектор, клонирует или копирует его, что-то делает с новым вектором (например, перетасовывает его) и возвращает его как новый собственный вектор. Как это можно сделать и каков самый идиоматический способ сделать это?

Попытка # 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, получает перемещен в функцию, перетасовывается, а затем передается обратно владельцу (через возвращаемое значение). Таким образом, исходный вектор модифицируется.

Я хочу знать, как передать вектор, который будет не изменяться, но имеет значения, клонированные в новый вектор в виде коробки и возвращаемый по завершении - как и на функциональном языке программирования, который имеет неизменные данные (например, Clojure).

4b9b3361

Ответ 1

Ваша попытка №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 или to_owned() из свойства ToOwned можно использовать для создания Vec<T> из &[T].

Существует также несколько способов получить &mut [T] из Vec<T>: нотация среза (&mut vec[..]), преобразование deref (&mut *vec) или вызов прямого метода (vec.as_mut_slice(), хотя этот устаревшее):

Ответ 2

Это, вероятно, то, что вы хотите:

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
}