I'm trying to write a piece of code that checks if an entry is in a cache, and if it isn't produce the value.
The problem is that to produce the value, I'd like to pass along the cache because the producer might want to use other values, or might want to insert their own.
Current code looks like:
#[derive(Default)]
pub struct R {}
#[derive(Hash, PartialEq, Eq, Clone)]
pub struct Mutation {}
fn create_mutations(s: &Mutation) -> Vec<Mutation> {
todo!();
}
fn expand(v1: &mut R, v2: &R) {
todo!();
}
pub fn rec_fn(cache: &mut HashMap<Mutation, R>, s: &Mutation) -> R {
let mut results: R = R::default();
let mutations = create_mutations(s);
for mutation in mutations {
if cache.get(&mutation).is_none() {
let r = rec_fn(cache, &mutation);
cache.insert(mutation.clone(), r);
}
let mutations_of_mutation = &cache[&mutation];
expand(&mut results, mutations_of_mutation);
}
results
}
The problem I have is that my Mutation block needs to be Clone.
I am wondering if I can write the block of the cache get & insert differently.
One way that looked promising, but was shut down by the borrow-checker was:
pub fn rec_fn(cache: &mut HashMap<Mutation, R>, s: &Mutation) -> R {
let mut results: R = R::default();
let mutations = create_mutations(s);
for mutation in mutations {
let mutations_of_mutation = cache.entry(mutation).or_insert_with_key(|m| rec_fn(cache, m));
expand(&mut results, mutations_of_mutation);
}
results
}
With the error:
error[E0500]: closure requires unique access to `*cache` but it is already borrowed
--> src/main.rs:97:78
|
97 | let mutations_of_mutation = cache.entry(mutation).or_insert_with_key(|m| rec_fn(cache, m));
| --------------------- ------------------ ^^^ ----- second borrow occurs due to use of `*cache` in closure
| | | |
| | | closure construction occurs here
| | first borrow later used by call
| borrow occurs here
I understand WHY this happens. But is there a way to write this without having clone mutation?