在参数化函数中复制/克隆向量的惯用Rust方法是什么?

quu*_*x00 43 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();
}
Run Code Online (Sandbox Code Playgroud)

失败:

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

即使我宣称newvec是可变的.我不明白为什么.

尝试#2

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

虽然这个编译,但它没有做我想要的.您传入的向量将shuffle_owned移动到函数中,进行洗牌,然后将其所有权转移回调用者(通过返回值).因此原始矢量被修改.

我想知道如何传入一个不会被变异的向量,但是将值克隆到一个新的盒装向量中并在完成时返回 - 就像在具有不可变数据的函数式编程语言(如Clojure)中那样.

Vla*_*eev 22

你的尝试#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
}
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为调用clone()一个切片会返回一个切片(即&[T]),并且你不能去&[T],&mut [T]因为你不能选择一个引用的可变性(借用指针).to_owned()但是,在调用时,您将获得一个新的实例,Vec<T>并且可以将其放入可变变量中以获取可变向量.

作为防锈1.0,无论是slice::to_vecto_owned()从方法ToOwned性状可以被用来创建Vec<T>&[T].

还有现在多种方式获取&mut [T]来自Vec<T>:切片符号(&mut vec[..]),则DEREF转换(&mut *vec)或直接方法调用(vec.as_mut_slice()虽然这个人是不建议使用):

  • 根据[documentation](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.as_mut_slice)的方法,vec.as_mut_slice()不被弃用。 (2认同)

A.B*_*.B. 9

这可能是你想要的:

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

要么

pub fn copy_shuffle<T: Clone>(vec: &[T]) -> Vec<T> {
    let mut vec = vec.to_vec();
    shuffle(&mut vec);
    vec
}
Run Code Online (Sandbox Code Playgroud)