Hello, I am learning Rust and I am trying to write a super simple interpreter as a practice project. I have hit a problem which starts with the following code:
use std::collections::HashMap;
struct Evaluator {
commands: HashMap<String, CommandPtr>,
}
type CommandFn = Fn(&mut Evaluator, &[&str]) -> bool;
type CommandPtr = Box<CommandFn>;
fn hello(_: &mut Evaluator, _: &[&str]) -> bool {
println!("Hello world");
return true;
}
fn main() {
let mut eval = Evaluator { commands: HashMap::new() };
eval.commands.insert(String::from("hello"), Box::new(hello));
// Call something in the evaluator - this bit is troublesome
if let Some(ref cmd) = eval.commands.get("hello") {
cmd(&mut eval, &["World"]);
}
}
Link to playground.
The compiler error is:
error[E0502]: cannot borrow `eval` as mutable because `eval.commands` is also borrowed as immutable
This problem has been driving me crazy as I end up in a loop of problems:
- To please the borrow monster I have to clone the command.
- I can't make CommandFn cloneable because it is a closure.
- I can't use my own cloneable trait for the command because of E0038.
Can anyone help me out of this maze?
Also, I don't understand the background behind the E0038 error. My mental model of traits is that they are like interfaces in Java or virtual methods in C++. However, if my mental model was correct, inheriting a trait would not prevent me from having a pointer to it -- something more must be happening.
Thanks in advance for any help.