Blubber
Blubber

Reputation: 1473

Borrowing mutable twice while using the same variable

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?

Upvotes: 5

Views: 6222

Answers (2)

hellow
hellow

Reputation: 13430

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);
    }
}

Upvotes: 2

starblue
starblue

Reputation: 56772

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);
}

Upvotes: 6

Related Questions