I'm learning Rust using The Rust Programming Language. I'm working on the following task in the chapter dealing with closures:
Try modifying
Cacher
to hold a hash map rather than a single value. The keys of the hash map will be thearg
values 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.value
directly has aSome
or aNone
value, the value function will look up thearg
in the hash map and return the value if it's present. If it's not present, theCacher
will call the closure and save the resulting value in the hash map associated with itsarg
value.
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?