Compiler errors 调用closure,即';s在集合中,具有集合的所有者

Compiler errors 调用closure,即';s在集合中,具有集合的所有者,compiler-errors,rust,borrow-checker,Compiler Errors,Rust,Borrow Checker,考虑以下代码: use std::collections::HashMap; type KeyCode = char; type CmdType = Fn(&mut E); struct E { key_map: HashMap<KeyCode, Box<CmdType>>, } impl E { fn map_key(&mut self, key: KeyCode, function: Box<CmdType>) {

考虑以下代码:

use std::collections::HashMap;
type KeyCode = char;
type CmdType = Fn(&mut E);

struct E {
    key_map: HashMap<KeyCode, Box<CmdType>>,
}

impl E {
    fn map_key(&mut self, key: KeyCode, function: Box<CmdType>) {
        self.key_map.insert(key, function);
    }
    fn quit(&mut self) { println!("quitting"); /* ... */ }
}

fn main() {
    let mut e = E { key_map: HashMap::new() };
    e.map_key('q', Box::new(|e: &mut E| e.quit()));

    match e.key_map.get(&'q') {
        Some(f) => f(&mut e),
        None => {}
    }
}
使用std::collections::HashMap;
类型KeyCode=char;
类型CmdType=Fn(&mut E);
结构E{
键映射:HashMap,
}
暗示{
fn映射键(&mut self,键:键代码,功能:框){
self.key\u映射插入(key,function);
}
fn退出(&mut self){println!(“退出”);/*…*/}
}
fn main(){
让mute=e{key_-map:HashMap::new()};
e、 map|u key('q',Box::new(|e:&mut e|e.quit());
匹配e.key_map.get(&'q'){
一些(f)=>f(&mut e),
无=>{}
}
}
这是因为我试图将
e
传递给
f

无法将
e
作为可变项借用,因为
e.key\u map
也作为不可变项借用

但是当
e.key\u map
的借用结束时,我将无法再访问
f
。那么,我该如何准确地称呼地图中的闭包呢

那么,我该如何准确地称呼地图中的闭包呢

这取决于什么行为是适当的

如您所知,如果
f
是从
e
借用的,则调用
f(&mut e)
是不可能的。解决办法是

  • 不要将
    &mut e
    传递给函数。如果
    E
    不在您的控制之下,这是不切实际的

  • 停止从
    e
    借用
    f
    。由于
    CmdType
    不能
    Clone
    复制,因此不能简单地将其复制出去。但是,您应该能够从地图中临时删除
    f

    let removed = e.key_map.remove(&'q');
    if let Some(f) = removed {
        f(&mut e);
        e.key_map.insert('q', f);
    }
    

一种解决方案是,如果合适的话,让
E
不拥有地图,而是将该功能与另一个结构分离。大概是这样的:

struct K {
    key_map: HashMap<KeyCode, Box<CmdType>>,
}

impl K {
    fn map_key(&mut self, key: KeyCode, function: Box<CmdType>) {
        self.key_map.insert(key, function);
    }
}

struct E;

impl E {
    fn quit(&mut self) { println!("quitting"); /* ... */ }
}

fn main() {
    let mut k = K { key_map: HashMap::new() };
    k.map_key('q', Box::new(|e: &mut E| e.quit()));

    let mut e = E;
    match k.key_map.get(&'q') {
        Some(f) => f(&mut e),
        None => {}
    }
}
struct K{
键映射:HashMap,
}
impl K{
fn映射键(&mut self,键:键代码,功能:框){
self.key\u映射插入(key,function);
}
}
结构E;
暗示{
fn退出(&mut self){println!(“退出”);/*…*/}
}
fn main(){
让mutk=k{key_-map:HashMap::new()};
k、 map|u key('q',Box::new(|e:&mut e|e.quit());
设mute=e;
匹配k.key_map.get(&'q'){
一些(f)=>f(&mut e),
无=>{}
}
}

E
如果需要,还可以引用
K
实例。

闭包必须以某种方式访问
E
。目前,我只是在
E
之外存储了
key\u map
,并在
E
中保留了对它的引用。这也不切实际,但至少是可行的。