help with borrow checker and self recursion inside a closure
Hi,
I'm new to rust and I'm at the "fighting the borrow checker" stage and I feel I need some help. I'm creating a solution to a puzzle problem. Uploaded the full code to the playpen although it reads data from the standard input at this point I'm trying to compile it.
Here is the relevant part that causes me headaches. I'm trying to memoize data into the cache hashmap and created a helper closure unwire that calls self.eval recursively and it captures self so I cannot borrow it for the match or later for the hashmap. I have a feeling that copy pasting the closures content into every location would compile but I did not try that (it would also be an unreadable mess). It is not clear to me what options do I have here.
struct Circuit {
connections: HashMap<String, Connection>,
cache: HashMap<String, u32>
}
impl Circuit {
fn eval(&mut self, id: &str) -> u32 {
if let Some(v) = self.cache.get(id) {
return *v;
}
let mut unwire = |w: &Wire| match *w {
Wire::Signal(a) => a,
Wire::Named(ref name) => self.eval(name)
};
let value = match *self.connections.get(id).unwrap() {
Connection::Direct(ref wire) => unwire(wire),
Connection::UnaryGate{ref op, ref a} => match *op {
Operation::NOT => !unwire(a),
_ => panic!() // invalid unary gate
},
Connection::BinaryGate{ref op, ref a, ref b} => match *op {
Operation::AND => unwire(a) & unwire(b),
Operation::OR => unwire(a) | unwire(b),
Operation::LSHIFT => unwire(a) << unwire(b),
Operation::RSHIFT => unwire(a) >> unwire(b),
_ => panic!() // invalid binary gate
}
};
self.cache.insert(id.to_owned(), value);
value
}
}
Originally I tried to do self.cache.entry(name).or_insert(self.eval(name)) inside the closure which looked cool and readable but every part of it wanted self exclusively so I moved the cache lookup and insert to different locations.
As always, thanks for any kind of help and I'm always open to any critique of my code.
Posted Feb 21, 2016, 10:09 PM UTC