1

I'm writing a program to calculate the frequency of word occurrence. This is a segment of my code.

// hm is a HashMap<&str, u32>
if let Some(val) = hm.get_mut(tt) {
    *val += 1u32;
} else {
    hm.insert(tt.clone(), 1u32);
}

And I got...

error: cannot borrow `hm` as mutable more than once at a time [E0499]
      hm.insert(tt.clone(), 1u32);
      ^~
note: first mutable borrow occurs here
            if let Some(val) = hm.get_mut(tt) {
                            ^~
note: first borrow ends here
            }
            ^
help: run `rustc --explain E0499` to see a detailed explanation

I can bypass this by moving hm.insert() out of else scope but it's kind of "un-programmatic" way... I tried using match but the same error (would obviously) happened.

How can I fix this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Frederick Zhang
  • 3,593
  • 4
  • 32
  • 54

1 Answers1

6

This is a common problem with HashMaps in Rust: borrows can't have ragged edges. Fortunately, there is an API to handle this case.

You can use HashMap::entry() to get a place on a hash map, occupied or vacant and then use or_insert() to set a value for the key if there is not one already.

*hm.entry(tt).or_insert(0u32) += 1;

This returns a reference to the hm location, filling it with 0 if it wasn't there, then increments whatever it was.

That Rust's lifetimes are prone to gratuitous conflicts is not an unknown issue. Here is a Rust's Rust core team member discussing plans to tackle this in a future version of Rust. For now, though, there are library methods that work around it.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366