I'm a beginner, and I'm on Chapter 13.1 of the book. The following appears as a suggested exercise:
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, thevalue
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.
Here is my attempt (what I think is the relevant part):
struct Cacher<T,K,V> where T: Fn(K) -> V,
K: std::cmp::Eq + std::hash::Hash,
{
calculation: T,
values: HashMap<K,V>,
}
impl<T,K,V> Cacher<T,K,V> where T: Fn(K) -> V,
K: std::cmp::Eq + std::hash::Hash,
{
fn new(calculation: T) -> Cacher<T,K,V> {
Cacher {
calculation,
values: HashMap::new(),
}
}
fn value(&mut self, arg: K) -> &V {
match self.values.get(&arg) {
Some(v) => v,
None => {
let result = (self.calculation)(arg);
self.values.insert(arg,result);
&result
}
}
}
}
However I get the following errors:
error[E0502]: cannot borrow `self.values` as mutable because it is also borrowed as immutable
--> src/main.rs:37:17
|
32 | fn value(&mut self, arg: K) -> &V {
| - let's call the lifetime of this reference `'1`
33 | match self.values.get(&arg) {
| ----------- immutable borrow occurs here
34 | Some(v) => v,
| - returning this value requires that `self.values` is borrowed for `'1`
...
37 | self.values.insert(arg,result);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
error[E0382]: use of moved value: `arg`
--> src/main.rs:37:36
|
32 | fn value(&mut self, arg: K) -> &V {
| --- move occurs because `arg` has type `K`, which does not implement the `Copy` trait
...
36 | let result = (self.calculation)(arg);
| --- value moved here
37 | self.values.insert(arg,result);
| ^^^ value used here after move
error[E0515]: cannot return reference to local variable `result`
--> src/main.rs:38:17
|
38 | &result
| ^^^^^^^ returns a reference to data owned by the current function
error[E0382]: borrow of moved value: `result`
--> src/main.rs:38:17
|
36 | let result = (self.calculation)(arg);
| ------ move occurs because `result` has type `V`, which does not implement the `Copy` trait
37 | self.values.insert(arg,result);
| ------ value moved here
38 | &result
| ^^^^^^^ value borrowed here after move
error: aborting due to 4 previous errors
Why is self.values borrowed immutably when I do self.values.get()? Isn't self passed as a mutable reference to the value function? How would I go about fixing this? I am a beginner. I will greatly appreciate it if someone can help me understand the concept better thanks.