Что такое идиоматический способ ржавчины для копирования/клонирования вектора в параметризованной функции?
Я пытаюсь написать параметризованную функцию, которая берет неизменный вектор, клонирует или копирует его, что-то делает с новым вектором (например, перетасовывает его) и возвращает его как новый собственный вектор. Как это можно сделать и каков самый идиоматический способ сделать это?
Попытка # 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).
Ответы
Ответ 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
}