从容器中检索和调用闭包

问题描述 投票:0回答:0

我正在尝试构建一个语言解释器。需要保持一个 命令的符号表作为机器状态的一部分。命令本身需要 能够向符号表添加新命令。

我目前的情况如下:

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
当满足某些条件
,所以这似乎是一种前进的方式,但我不确定究竟如何。

正确的做法是什么?

rust closures traits ownership
© www.soinside.com 2019 - 2024. All rights reserved.