I am trying to implement a Cacher
as mentioned in Chapter 13 of the Rust book and running into trouble.
My Cacher
code looks like:
use std::collections::HashMap;
use std::hash::Hash;
pub struct Cacher<T, K, V>
where
T: Fn(K) -> V,
{
calculation: T,
values: HashMap<K, V>,
}
impl<T, K: Eq + Hash, V> Cacher<T, K, V>
where
T: Fn(K) -> V,
{
pub fn new(calculation: T) -> Cacher<T, K, V> {
Cacher {
calculation,
values: HashMap::new(),
}
}
pub fn value(&mut self, k: K) -> &V {
let result = self.values.get(&k);
match result {
Some(v) => {
return v;
}
None => {
let v = (self.calculation)(k);
self.values.insert(k, v);
&v
}
}
}
}
and my test case for this lib looks like:
mod cacher;
#[cfg(test)]
mod tests {
use cacher::Cacher;
#[test]
fn repeated_runs_same() {
let mut cacher = Cacher::new(|x| x);
let run1 = cacher.value(5);
let run2 = cacher.value(7);
assert_ne!(run1, run2);
}
}
I ran into the following problems when running my test case:
error[E0499]: cannot borrow cacher as mutable more than once at a time
Each time I make a run1, run2 value it is trying to borrowcacher
as a mutable borrow. I don't understand why it is borrowing at all - I thoughtcacher.value()
should be returning a reference to the item that is stored in thecacher
which is not a borrow.error[E0597]: v does not live long enough
pointing to the v I return in the None case of value(). How do I properly move thev
into theHashMap
and give it the same lifetime as theHashMap
? Clearly the lifetime is expiring as it returns, but I want to just return a reference to it to use as the return from value().error[E0502]: cannot borrow
self.valuesas mutable because it is also borrowed as immutable
in value().self.values.get(&k)
is an immutable borrow andself.values.insert(k,v)
is a mutable borrow - though I thought.get()
was an immutable borrow and.insert()
was a transfer of ownership.
and a few other errors related to moving which I should be able to handle separately. These are much more fundamental errors that indicate I have misunderstood the idea of ownership in Rust, yet rereading the segment of the book doesn't make clear to me what I missed.