HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustCritical

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

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
idiomaticfunctionclonethecopyvectorwayrustwhatparameterized

Problem

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(vec: &mut [T]) {
    // ... contents removed: it shuffles the vector in place
    // ... so needs a mutable vector
}

pub fn shuffle_create_new(vec: &[T]) -> Vec {
    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(mut vec: Vec) -> Vec {
    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).

Solution

Your attempt #1 is almost correct, you just have to move to_owned() to the first line:

fn shuffle(vec: &mut [T]) {
    // ...
}

fn shuffle_create_new(vec: &[T]) -> Vec {
    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 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 from &[T].

There are also now several ways to obtain &mut [T] from Vec: the slicing notation (&mut vec[..]), the deref conversion (&mut *vec) or the direct method call (vec.as_mut_slice(), though this one is deprecated):

Code Snippets

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
}

Context

Stack Overflow Q#21369876, score: 104

Revisions (0)

No revisions yet.