我正在尝试编写一个参数化函数,该函数接受不可变向量,克隆或复制它,对新向量执行某些操作(例如将其混淆)并将其作为新拥有的向量返回。如何做到这一点以及最常用的方法是什么?
尝试#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)。
答案 0 :(得分:20)
您的尝试#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开始,ToOwned
特征中的slice::to_vec
或to_owned()
方法可用于从Vec<T>
创建&[T]
。
现在还有几种方法可以从&mut [T]
获取Vec<T>
:切片符号(&mut vec[..]
),deref转换(&mut *vec
)或直接方法调用( vec.as_mut_slice()
,虽然这个已弃用):
答案 1 :(得分:7)
这可能是你想要的:
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
}