How to update a list by the immutable reference 【cannot borrow `self.list` as immutable】

struct StringIter {
    current: Option<usize>,
    list: Vec<Vec<u8>>,
    len: usize,
}

impl StringIter {
    fn iter(&mut self) {
        for i in 0..self.len {
            let current = self.current.unwrap();
            if i != current {
                self.list[i].extend_from_slice(&self.list[current].as_slice());
            }
        }
    }
}

fn main() {}

or simply version:

let mut s = vec![vec![1],vec![2]];
s[0].extend_from_slice(s[1].as_slice());

The compiler says cannot borrow self.list as immutable, actually I know the reason, but I can't find a way to fix this.

I googled it and got some ideas:

But I can't find a way to split the list and make the compiler happy, how can I archive this? Is there a best practice?

Many thanks.

You can obtain mutable access to multiple elements by using slice patterns, like this:

let mut s = vec![vec![1],vec![2]];
match &mut *s {
    [first, second, ..] => {
        first.extend_from_slice(second.as_slice());
    }
    _ => {} // handle index out of bounds
}
1 Like

Oh, that's amazing, thanks for your answer, it really works for the simply version.
But the code is like this, is there an elagant way to fix it? By the way, I don't know if slice patterns work for the unknown index.

impl StringIter {
    fn iter(&mut self) {
        for i in 0..self.len {
            let current = self.current.unwrap();
            if i != current {
                self.list[i].extend_from_slice(self.value());
            }
        }
    }

    fn value(&self)->&[u8]{
        // do something
        let current = self.current.unwrap();
        &self.list[current]
    }
}

I find a hack way to archive it with slice patterns, :joy: :joy: :joy: :joy:, just not elegant.

struct StringIter {
    current: Option<usize>,
    list: Vec<Vec<u8>>,
    len: usize,
}

fn do_something(a: &mut Vec<u8>, b: &mut Vec<u8>) {}

impl StringIter {
    fn iter(&mut self) {
        for i in 0..self.len {
            let curr = self.current.unwrap();
            if i != curr {
                if i > curr {
                    match &mut self.list[curr..i+1] {
                        [curr, .., i] => {
                            do_something(curr, i);
                        }
                        _ => {} // handle index out of bounds
                    }
                } else {
                    match &mut self.list[i..curr+1] {
                        [i, .., curr] => {
                            do_something(i, curr);
                        }
                        _ => {} // handle index out of bounds
                    }
                }
            }
        }
    }

    fn value(&self) -> &[u8] {
        let current = self.current.unwrap();
        &self.list[current]
    }
}

fn main() {
}

You can also use split_at_mut and friends to get the multiple mutable pieces.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.