I would like to remove a random element from a HashMap. However, I kept getting this error.
error[E0502]: cannot borrow `self.map` as mutable because it is also borrowed as immutable
--> src/main.rs:23:9
|
21 | let key_to_delete = self.map.keys().skip(x).next().unwrap();
| -------- immutable borrow occurs here
22 | println!("key_to_delete: {:?}", key_to_delete);
23 | self.map.remove(&key_to_delete);
| ^^^^^^^^^------^^^^^^^^^^^^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0502`.
However, if I add a .clone() at the end of that line, the error is gone. While I fixed this problem (mostly by trials and errors), I still don't understand why it works. Specifically, why does this error showed up in the first place? Shouldn't the immutable reference to self.map get dropped after the line
let key_to_delete = self.map.keys().skip(x).next().unwrap()
finish executing?
In this example, the key is of type i32, which only takes 4 byte. Therefore, it's OK to clone. But what if the key is some large struct or clone is not desirable for other reasons? How then should I solve this problem?
Another observation is that my IDE (Intellij with rust plugin) showed that the type of key_to_delete is &i32 if I don't have .clone() and i32 if I do. I am not sure if this matters.
Any clarification is appreciated.
Here is my code.
use std::collections::HashMap;
use rand::{Rng, thread_rng};
#[derive(Debug)]
struct MyStruct {
map: HashMap<i32, i32>,
}
impl MyStruct {
fn new() -> Self {
MyStruct { map: HashMap::new() }
}
fn add(&mut self, key: i32, value: i32) {
self.map.insert(key, value);
println!("after add: {:?}", self.map);
}
fn delete(&mut self) {
let x: usize = thread_rng().gen_range(0..self.map.len());
let key_to_delete = self.map.keys().skip(x).next().unwrap().clone(); // this "clone" is critical
println!("key_to_delete: {:?}", key_to_delete);
self.map.remove(&key_to_delete);
println!("map after delete: {:?}", self.map);
}
}
fn main() {
let mut c = MyStruct::new();
c.add(1, 2);
c.add(3, 4);
c.add(5, 6);
c.delete();
}