1

I have this code where pat_vec and str_vec are two iterators:

let mut pat_mapping: HashMap<char, &str> = HashMap::new();

for combi in pat_vec.zip(str_vec) {
    let (c, word) = combi;

    match pat_mapping.get(&c) {
        Some(phrase) => {
            if phrase.to_string() != word.to_string() {
                return false;
            }
        }

        None => {
            pat_mapping.insert(c, word);
        }
    }
}

This does not work, and the compiler complains that:

cannot borrow `pat_mapping` as mutable because it is also borrowed as immutable [E0502]

I understand that it might because pat_mapping.get(&c) borrowed &self as immutable, while the insert() method falls into the same scope but needs to borrow &self as mutable.

I have a work around:

match word_mapping.get(&c) {
    Some(phrase) => {
        if phrase.to_string() != word.to_string() {
            return false;
        }
    }
    None => {

        pat_trigger = true;
    }

};

if pat_trigger {
    pat_mapping.insert(c, word);
}

But introducing a boolean flag is redundant. Is there a way to work around the borrow check so as to do the match and insert in the same code block?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
divinites
  • 109
  • 4

1 Answers1

3

You want to use entry:

match pat_mapping.entry(c) {
    Occupied(phrase) => {
        if phrase.get().to_string() != word.to_string() {
            return false;
        }
    },
    Vacant(vacant) => {
        vacant.insert(word);
    }
}

It also has the advantage of looking up the key only once.

mcarton
  • 27,633
  • 5
  • 85
  • 95