Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the idiomatic Rust way to copy/clone a vector in a parameterized function?

Tags:

rust

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).

like image 949
quux00 Avatar asked Jan 26 '14 22:01

quux00


People also ask

What is difference between copy and clone in Rust?

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.

Does VEC implement clone?

You can't Copy , but you can use vec. clone() for your single-line assignment. Great!

What is a rust vector?

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.


1 Answers

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):

like image 94
Vladimir Matveev Avatar answered Sep 23 '22 20:09

Vladimir Matveev