I'm learning Rust using The Rust Programming Language. I'm working on the following task in the chapter dealing with closures:
Try modifying
Cacherto hold a hash map rather than a single value. The keys of the hash map will be theargvalues that are passed in, and the values of the hash map will be the result of calling the closure on that key. Instead of looking at whetherself.valuedirectly has aSomeor aNonevalue, the value function will look up theargin the hash map and return the value if it's present. If it's not present, theCacherwill call the closure and save the resulting value in the hash map associated with itsargvalue.
This is my solution:
use std::collections::HashMap;
struct Cacher<T>
where
    T: Fn(i32) -> i32,
{
    calculation: T,
    values: HashMap<i32, i32>,
}
impl<T> Cacher<T>
where
    T: Fn(i32) -> i32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            values: HashMap::new(),
        }
    }
    fn value(&mut self, arg: i32) -> i32 {
        match self.values.get(&arg) {
            Some(v) => *v,
            None => {
                let v = (self.calculation)(arg);
                self.values.insert(arg, v);
                v
            }
        }
    }
}
Compiler error:
error[E0502]: cannot borrow `self.values` as mutable because it is also borrowed as immutable
  --> src/main.rs:26:17
   |
22 |         match self.values.get(&arg) {
   |               ----------- immutable borrow occurs here
...
26 |                 self.values.insert(arg, v);
   |                 ^^^^^^^^^^^ mutable borrow occurs here
...
29 |         }
   |         - immutable borrow ends here
I can solve this by using:
match self.values.clone().get(&arg) { ...
Do I really need to clone the whole HashMap to use it in the match-statement and inserting a value afterwards?