Here is my first solution. It's working but I don't understand why:
// Make me compile without changing line 9! Scroll down for hints :)
pub fn main() {
let vec0: Vec<i32> = Vec::new();
// Just borrow vec0 instead of taking ownership of it
let mut vec1 = fill_vec(&vec0);
// This line cannot be changed
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
# Change argument type to &Vec<i32>
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut new_vec: Vec<i32> = Vec::new();
// I thought I had to dereference vec, since its type is &Vec<i32>,
// which reads as "reference to a Vec of i32" (if I'm not mistaken),
// and I cannot iterate over a reference.
//
// for i in *vec {
// new_vec.push(i);
// }
//
// But it does not work. and I don't understand why.
// Error is "cannot move out of borrowed content"
// This works though, but I just tried it randomly,
// so not sure why. How come I have to dereference `i`?
// Very confused here...
for i in vec {
new_vec.push(*i);
}
new_vec.push(22);
new_vec.push(44);
new_vec.push(66);
new_vec
}
Also, is that the correct way to copy a vector? I looked for a copy() function but did not find that.
Hope this kind of question is approriate on the forum since questions seems more general.
first things first, here's another working solution (Rust Playground)
pub fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(&vec0);
// Do not change the following line!
println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(vec: &Vec<i32>) -> Vec<i32> {
let mut vec = vec.to_vec(); // this copies the vector for if T is `Clone`
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
And a few explanations:
Vector Iterators iterate over references to items of the collection Iter in std::slice - Rust This avoids moving them out and allows to modify them.
You generally don't need to dereference when calling a method in Rust. Rust has compiler support for dereferencing at the appropriate points.
let vec0 = vec![1, 2, 3];
// This will work perfectly because the `for` loop calls `into_iter()`
// on the vec converting it into something iterable. It is moved
// in the process so `vec` is no longer accessible.
for v in vec0 { println!("{}", v); }
let vec1 = &vec![1, 2, 3];
// This is a bit different. This calls `into_iter()` on the borrowed vector
// which does something depending on the implementation but at the
// most *cannot* modify or move the borrow. `into_iter()` on a borrowed vector
// calls `iter()` on the vec which yields borrows to each element.
for v in vec1 { println!("{}", *v); }
let vec2 = &vec![1, 2, 3];
// A `for` loop always calls `into_iter()` but sometimes the fact that
// you're working with a borrowed value may not be obvious. To make
// this more clear, you dereference first and then borrow.
for v in &*vec2 { println!("{}", *v); }
// Since a proper implementation of `into_iter()` should defer to `iter`
// and `iter_mut` in the appropriate cases, association of `iter` with `&`
// and `iter_mut` with `&mut` seems appropriate.
let mut vec3 = vec![1, 2, 3];
for v in &mut vec3 { println!("mutating {} in vec3", v); *v += 1; }
for v in &vec3 { println!("borrowing {} from vec3", v); }
for v in vec3 { println!("consumed vec3 and looking at {}", v); }
sorry to replying to an old topic. Since I'm also solving rustlings excersie. And This came in google search.
As per "Rust in Motion" book explanation;
One should avoid .copy as it will increase memory load.
you should instead Borrow with reference
so in this case taking fill_vec(vec: &Vec<i32>) is correct solution. Since it also makes clear to the reader what is the purpose of this Borrow.