Хотите добавить в HashMap с помощью сопоставления с шаблоном, получить изменяемый заем более одного раза за раз
Я пытаюсь написать какой-нибудь игрушечный код, который хранит количество раз, когда он видит слово в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]
сейчас.
Я чувствую, как этот методдолжен работать, но мне не хватает трюка. Что я делаю неправильно?
РЕДАКТИРОВАТЬ: я понимаю, что я могу сделать это с помощью
if c.contains_key(word) {
if let Some(i) = c.get_mut(s) {
*i += 1;
}
} else {
c.insert(word.to_string(), 1);
}
но это кажется ужасно уродливым кодом против сопоставления с образцом (особенноcontains_key()
проверить как если, а затем, по сути, сделать эту проверку еще раз, используяSome
.