Я пытаюсь написать код игрушки, в котором хранится количество раз, когда оно видит слово в HashMap
. Если ключ существует, он увеличивает счетчик на единицу, если ключ не существует, он добавляет его со значением 1
. Я инстинктивно хочу сделать это с совпадением шаблонов, но я попал в заимствование с изменением более чем один раз:
fn read_file(name: &str) -> io::Result<HashMap<String, i32>> {
let b = BufReader::new(File::open(name)?);
let mut c = HashMap::new();
for line in b.lines() {
let line = line?;
for word in line.split(" ") {
match c.get_mut(word) {
Some(i) => {
*i += 1;
},
None => {
c.insert(word.to_string(), 1);
}
}
}
}
Ok(c)
}
Ошибка, которую я получаю:
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> <anon>:21:21
|
16 | match c.get_mut(word) {
| - first mutable borrow occurs here
...
21 | c.insert(word.to_string(), 1);
| ^ second mutable borrow occurs here
22 | }
23 | }
| - first borrow ends here
Я понимаю, почему компилятор сварливый: я сказал, что собираюсь изменить значение, введенное в значение word
, но тогда вставка не находится в этом значении. Однако вставка находится на None
, поэтому я подумал бы, что компилятор мог убедиться, что теперь нет возможности мутировать c[s]
.
Я чувствую, что этот метод должен работать, но мне не хватает трюка. Что я делаю неправильно?
EDIT: Я понимаю, что могу сделать это, используя
if c.contains_key(word) {
if let Some(i) = c.get_mut(s) {
*i += 1;
}
} else {
c.insert(word.to_string(), 1);
}
но это кажется ужасно уродливым кодом по сравнению с совпадением шаблонов (в частности, нужно выполнить проверку contains_key()
как if, а затем, по существу, выполнить эту проверку снова, используя Some
.