Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the last element of a vector and push it to the same vector

Tags:

vector

rust

What I am trying to do:

enum Test {
    Value1,
    Value2,
    Value3
}

fn main() {
    let mut test_vec: Vec<Test> = Vec::new();
    test_vec.push(Test::Value2);

    if let Some(last) = test_vec.last() {
        test_vec.push(*last);
    }
    //Wanted output: vector with [Test::Value2, Test::Value2]
}

I understand that when I call last(), it will return Option<&Test> So it will borrow the test_vec till the end of the if-let block.

I tried the following without success:

if let Some(last) = test_vec.last().map(|v| v.clone()) {
    test_vec.push(*last);
}

//and

let last = test_vec.last().unwrap().clone();
test_vec.push(*last);
like image 948
Bram Avatar asked Jun 01 '16 22:06

Bram


1 Answers

When trying to figure out why the borrow checker complains it can be useful to identify the types involved.

If you type out:

let _: () = test_vec.last().map(|v| v.clone());

you get an error complaining that () and core::option::Option<&Test> are not the same type.

What's going on? Very simply put, if you clone an &Test you get an &Test, thus calling .map(|v| v.clone()) on a Option<&Test> gives an Option<&Test>. Obviously, it still borrows.

The same problem occurs with your next attempt, if you type out:

let _: () = test_vec.last().unwrap().clone();

you get an error complaining that () and &Test are not the same type.

By calling unwrap on an Option<&Test> you get an &Test which is then cloned into an &Test.


So, the problem is a lack of dereferencing. You need to dereference earlier, to avoid borrowing test_vec in Some(last):

if let Some(last) = test_vec.last().map(|v| (*v).clone()) {
    test_vec.push(last);
}

of course, this does not work because Test does not implement clone. Once that is fixed (by #[derive(Clone)]), it compiles.

Since cloning from references is such a common need, there is a dedicated method on Option (and Iterator) called cloned:

if let Some(last) = test_vec.last().cloned() {
    test_vec.push(last);
}
like image 195
Matthieu M. Avatar answered Sep 29 '22 16:09

Matthieu M.