I'm new to Rust and I met this situation which I think can be solved with more concise code, which is however rejected by the borrow checker. I'd like to know whether there's an alternative approach to it.
I'm trying to construct an inverted index. If the key is not previously in the HashMap
, I have to create a new postings_list
and insert it. If the key was already there, I will presumably have to only update the originally existing postings_list
, instead of replacing it.
The code that is working (very long-winded):
if !terms.contains_key(term) {
let mut postings_list = Vec::new();
postings_list.push(posting_id);
terms.insert(term.to_string(), postings_list);
} else {
// try! can't even be used with Option... So I'm forced to write another match!
// let postings_list = try!(terms.get_mut(term));
match terms.get_mut(term) {
Some(postings_list) => {
postings_list.push(posting_id);
},
// It's impossible for this to happen...
None => process::exit(999)
}
}
However, I feel one call to get_mut
should suffice:
match terms.get_mut(term) {
None => {
let mut postings_list = Vec::new();
postings_list.push(posting_id);
terms.insert(term.to_string(), postings_list);
},
Some(postings_list) => {
postings_list.push(posting_id);
}
}
The borrow checker says I borrowed a mutable reference twice, at terms.get_mut(term)
and terms.insert(term.to_string(), postings_list);
.
The problem for me is that apparently calling contains_key
and also get_mut
both would be much less efficient than just performing one check. Or did I get it wrong? Also, the above code is much uglier.
Am I doing this wrong? Or should I just not use get_mut
, and should instead use get
and then insert
an updated postings_list
again? Again, I'd think that would be much less efficient than simply operating on the original list stored in the HashMap
itself. Or am I wrong?