I'm trying to write a parameterized function that takes an immutable vector, clones or copies it, does something to the new vector (such as shuffle it) and returns it as a new owned vector. How can this be done and what is the most idiomatic way to do it?
Attempt #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();
}
Fails with:
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/main.rs:8:13
|
8 | shuffle(&mut newvec);
| ^^^^^^^^^^^ cannot borrow as mutable
even though I declared newvec
as mutable. I don't understand why.
Attempt #2
pub fn shuffle_owned<T: Clone>(mut vec: Vec<T>) -> Vec<T> {
shuffle(&mut vec);
return vec;
}
While this compiles, it doesn't do what I want. The vector you pass into shuffle_owned
gets moved into the function, shuffled and then has its ownership transferred back to the caller (via the return value). So the original vector is modified.
I want to know how to pass in a vector that will not be mutated, but have the values cloned into a new boxed vector and returned when finished - as you do in a functional programming language that has immutable data (such as Clojure).
This is probably what you want:
or
Your attempt #1 is almost correct, you just have to move
to_owned()
to the first line:This happens because calling
clone()
on a slice will return you a slice (i.e.&[T]
), and you cannot go from&[T]
to&mut [T]
because you cannot choose mutability of a reference (borrowed pointer). When you callto_owned()
, however, you are getting a fresh instance ofVec<T>
and you can put it into a mutable variable to get mutable vector.As of Rust 1.0, either
slice::to_vec
orto_owned()
method from theToOwned
trait can be used to createVec<T>
from&[T]
.There are also now several ways to obtain
&mut [T]
fromVec<T>
: the slicing notation (&mut vec[..]
), the deref conversion (&mut *vec
) or the direct method call (vec.as_mut_slice()
, though this one is deprecated):