Why can I not update the Vector inside the hash here?
I'm getting:
cannot borrow data in a & reference as mutable
fn main() {
let text = "
# section 1
blah blah
qwerty
# section 2
zxcvbn
woup dee woup
";
let lines = &text.lines().collect();
parse(lines);
}
use std::collections::HashMap;
fn parse(lines: &Vec<&str>) {
let mut started = false;
let mut langs = HashMap::new();
let mut k: &str;
for line in lines {
if line.starts_with("# ") {
started = true;
k = line[2..].trim();
let v = vec![*line];
langs.insert(k, v);
} else {
if started {
langs[k].push(*line)
} else {
continue;
}
}
}
for (k, v) in langs.iter() {
println!("{}:", k);
for w in v.iter() {
println!("\t{}", w);
}
}
}
Use .get_mut(k).unwrap() (to .push(*line)) rather than [k] since HashMap does not seem to implement the IndexMut trait (it only implements Index, which only yields shared references).
As to why that is, I don't know; it looks like an oversight.
Should &mut map[el] make a new element if el is not in the hashmap?
How about map[el] = value;?
If your answers differed, then Rust can't implement IndexMut for HashMap because there is no way to distinguish between the two cases. Inserting on a mutable borrow is a footgun, because it differs from simply doing map.get_mut(el).unwrap(), this difference would make it prone to bugs.
I should take the opportunity to mention that for mutation, there's also the entry interface when you want to be able to manipulate a key's entry in the map, with the ability to determine if it's occupied or not, with useful functions to insert and update the values.
This lets you say succinct things like m.entry(k).or_default().push(*x).