2

考虑以下代码:

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 => {}
    }
}

无法编译,因为我试图传递ef

不能借用e为可变的,因为e.key_map它也被借用为不可变的

但是当借完的时候e.key_map我就再也无法接触到了f。那么我如何准确地调用地图内的闭包呢?

4

2 回答 2

1

那么我如何准确地调用地图内的闭包呢?

这取决于什么行为是合适的。

如您所见,如果从 借用,f(&mut e)则无法调用。解决方案是fe

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

  • 停止f向 借款e。既然CmdType不能Clone,就不能简单的抄出来。但是,您应该能够暂时f从地图中删除:

    let removed = e.key_map.remove(&'q');
    if let Some(f) = removed {
        f(&mut e);
        e.key_map.insert('q', f);
    }
    
于 2015-08-20T02:35:43.347 回答
0

如果合适的话,一种解决方案是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 => {}
    }
}

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

于 2015-08-20T14:53:55.670 回答