Search code examples
rustvector

Change last entry of vector filled with arrays


for my programm I want to fill a vector with arrays containing integers, but at some point I might want to manipulate the last entry in the vector if present. I aim to perform this efficiently as possible. So I thought to do it in the following way. I tried to change the code and get it working, but I failed so far. I hope someone can help me, so I provided a minimum example I work on to understand the issue.

fn main() {
    let mut test_vec: Vec<[i8; 3]> = vec![];
    test_vec.push([1, 2, 3]);
    test_vec.push([4, 5, 6]);
    match test_vec.last() {
        Some(v) => {
            v[2] = 0;  // this does not work <= need help!
        }
        None => {}
    }
    test_vec.push([7, 8, 9]);
    match test_vec.last() {
        Some(v) => {
            v[1] = 0;  // this also fails <= need help!
        }
        None => {}
    }

    for entry in test_vec {
        println!("{entry:?}");  // should print [1, 2, 3], [4, 5, 0] and [7, 0, 9]
    }
}

Solution

  • [T]::last returns Option<&T>. This is shared reference, which cannot be used to modify pointed to data. Use [T]::last_mut, which returns Option<&mut T>.

    fn main() {
        let mut test_vec: Vec<[i8; 3]> = vec![];
        test_vec.push([1, 2, 3]);
        test_vec.push([4, 5, 6]);
        if let Some(v) = test_vec.last_mut() {
            v[2] = 0;
        }
        test_vec.push([7, 8, 9]);
        if let Some(v) = test_vec.last_mut() {
            v[1] = 0;
        }
    
        for entry in test_vec {
            println!("{entry:?}");  // prints [1, 2, 3], [4, 5, 0] and [7, 0, 9]
        }
    }
    

    Note that Rust compiler tries to suggest this solution, by telling you to change binding from &[...] to &mut [...].

    error[E0594]: cannot assign to `v[_]`, which is behind a `&` reference
     --> src/main.rs:7:13
      |
    6 |         Some(v) => {
      |              - consider changing this binding's type to be: `&mut [i8; 3]`
    7 |             v[2] = 0;
      |             ^^^^^^^^ `v` is a `&` reference, so the data it refers to cannot be written