[solved] Getting a mutable reference of a vector element


#1

I have a function get_elem that takes a reference to a mutable vector, a search criteria, and optionally returns a mutable reference to an element that matches. For example:

fn get_elem<'a>(v: &'a mut Vec<i32>, i: i32) -> Option<&'a mut i32> {
    v.iter_mut().find(|x| **x > i)
}

Beautiful and simple! But let’s say I didn’t want to use find() and instead wanted to use a plain ol’ for-loop. Something like this:

fn get_elem2<'a>(v: &'a mut Vec<i32>, i: i32) -> Option<&'a mut i32> {
    for &mut elem in v {
        if elem > i {
            return Some(&mut elem)
        }
    }
    None
}

This fails to compile with the following lifetime error:

a.rs:10:30: 10:34 error: `elem` does not live long enough
a.rs:10             return Some(&mut elem)

I think if I could tell the compiler that the thing that elem references has lifetime 'a then I would be good. Is what I want to do possible?

Thanks!


#2

Just dont do for &mut elem ... :smile:

fn get_elem2<'a>(v: &'a mut Vec<i32>, i: i32) -> Option<&'a mut i32> {
    for elem in v {
        if *elem > i {
            return Some(elem)
        }
    }
    None
}

This keeps elem as the original reference, with the original lifetime. Doing return Some(&mut elem) returns a new reference that is only valid within the for scope.


#3

If you write &mut elem in the return value, you are not returning a pointer to the array element but a pointer to the local variable elem. Pointer to local variable → big no.

Fortunately, the cursor in a for loop on a vector is already a pointer. By writing &mut elem in the for loop, you are actually matching the target of the pointer, turning it into the pointed value.

So: (1) remove &mut from the for clause to have the real pointer; (2) return Some(elem) directly, and (3) dereference the pointer in the comparison: *elem > i.

Well… Someone beat me to the answer.


#4

You wrote a nicer explanation. :wink:


#5

Ah! Ok, yes that all makes perfect sense, I just wasn’t thinking about what I had actually written. Thanks all