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).
Differs from Copy in that Copy is implicit and extremely inexpensive, while Clone is always explicit and may or may not be expensive. In order to enforce these characteristics, Rust does not allow you to reimplement Copy , but you may reimplement Clone and run arbitrary code.
You can't Copy , but you can use vec. clone() for your single-line assignment. Great!
Vector is a module in Rust that provides the container space to store values. It is a contiguous resizable array type, with heap-allocated contents. It is denoted by Vec<T>. Vectors in Rust have O(1) indexing and push and pop operations in vector also take O(1) complexity.
Your attempt #1 is almost correct, you just have to move to_owned()
to the first line:
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 }
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 call to_owned()
, however, you are getting a fresh instance of Vec<T>
and you can put it into a mutable variable to get mutable vector.
As of Rust 1.0, either slice::to_vec
or to_owned()
method from the ToOwned
trait can be used to create Vec<T>
from &[T]
.
There are also now several ways to obtain &mut [T]
from Vec<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):
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With