2
votes

Suppose that I'm going through a vector (not necessarily linearly, so I can't just use map) and I need to change an element when it satisfies some condition. I would think to use some variable to keep track of where I am, for example, something like a current variable

let mut v = vec![1, 2, 3, 4];

let mut current = &mut v[0];

and then check current to for some condition to see if it needs to be changed. However, when I do

current = &mut v[1];

It gives me the cannot borrow v as mutable more than once at a time.

I feel like this should be allowed, since I've only used one variable, and I can't access the old borrow any more.

Is there some way I can let rust know that I'm giving the first borrow back, so I'm not borrowing twice? Or have I been thinking about this wrong, and there is a different rust idiom I should use? I've solved this problem by using the indeces for the vector instead of a mutable reference, but I think this problem of "traversing using a current and then changing it" goes beyond just vectors. What if the data structure I had didn't have indeces?

2
For the problem I was doing, I wasn't going through the vector linearly. Would making a custom iterator be the best way? - Blubber
If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved to your satisfaction, and it gives the person that helps you credit for the assist. See here for a full explanation. - hellow

2 Answers

5
votes

The mutable reference exists until the variable goes out of scope, so you can have several mutable borrows in sequence by putting blocks around each one:

fn do_stuff(n: &mut usize) {
    *n += 1;
}

fn main() {
    let mut v = vec![1, 2, 3, 4];
    {
        let current = &mut v[1];
        do_stuff(current);
    }
    {
        let current = &mut v[0];
        do_stuff(current);
    }
    println!("{:?}", v);
}

This is unnecessary with non-lexical lifetimes, which are currently only available on the nightly version:

#![feature(nll)]

fn do_stuff(n: &mut usize) {
    *n += 1;
}

fn main() {
    let mut v = vec![1, 2, 3, 4];

    let mut current = &mut v[1];
    do_stuff(current);

    current = &mut v[0];
    do_stuff(current);

    println!("{:?}", v);
}
2
votes

If you want to access more than one, you have to create a scope.

fn main() {
    let mut vec = vec![2, 3, 5];
    {
        let mut current1 = vec.get_mut(1);
        println!("{:?}", current1);
    }
    {
        let mut current2 = vec.get_mut(2);
        println!("{:?}", current2);
    }

    for i in 0..3 {
        let mut current = vec.get_mut(i);
        println!("{:?}", current);
    }
}