我正在尝试构建一个语言解释器。需要保持一个 命令的符号表作为机器状态的一部分。命令本身需要 能够向符号表添加新命令。
我目前的情况如下:
struct Machine<'a> {
dict: HashMap<&'a str, Box<dyn Fn(&mut Machine) -> ()>>,
}
对于从符号表执行命令的解释器函数,我有 (简化):
fn exec(m: &mut Machine, instr: &str) {
let f = m.dict.get(instr).unwrap();
f(m);
}
这给了我一个编译器错误:
error[E0502]: cannot borrow `*m` as mutable because it is also borrowed as immutable
--> src/mre.rs:9:5
|
8 | let f = m.dict.get(instr).unwrap();
| ----------------- immutable borrow occurs here
9 | f(m);
| -^^^
| |
| mutable borrow occurs here
| immutable borrow later used by call
我知道为什么这是不安全的;在允许所有命令删除它之后 符号表中自己的条目。我认为正确的前进方式是 在我使用它之前克隆
f
,这样m.dict
的借用可以在
打电话给f
.
天真地尝试给了我:
fn exec(m: &mut Machine, instr: &str) {
let f = (*m.dict.get(instr).unwrap()).clone();
f(m);
}
error[E0599]: the method `clone` exists for struct `Box<dyn for<'r, 's> Fn(&'r mut Machine<'s>)>`, but its trait bounds were not satisfied
--> src/mre.rs:8:43
|
8 | let f = (*m.dict.get(instr).unwrap()).clone();
| ----------------------------- ^^^^^
| |
| this is a function, perhaps you wish to call it
|
::: /home/ari/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:74:1
|
74 | pub trait Fn<Args>: FnMut<Args> {
| -------------------------------
| |
| doesn't satisfy `dyn for<'r, 's> Fn(&'r mut Machine<'s>): Clone`
| doesn't satisfy `dyn for<'r, 's> Fn(&'r mut Machine<'s>): Sized`
|
::: /home/ari/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:194:1
|
194 | / pub struct Box<
195 | | T: ?Sized,
196 | | #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
197 | | >(Unique<T>, A);
| |_- doesn't satisfy `_: Clone`
|
= note: the following trait bounds were not satisfied:
`dyn for<'r, 's> Fn(&'r mut Machine<'s>): Sized`
which is required by `Box<dyn for<'r, 's> Fn(&'r mut Machine<'s>)>: Clone`
`dyn for<'r, 's> Fn(&'r mut Machine<'s>): Clone`
which is required by `Box<dyn for<'r, 's> Fn(&'r mut Machine<'s>)>: Clone`
Box<T>
在 Clone
执行时执行 T
。闭包是 Clone
当满足某些条件,所以这似乎是一种前进的方式,但我不确定究竟如何。
正确的做法是什么?