Rust 中的方法数组

Array of methods in Rust

我正在尝试用 Rust 编写请求 "router":与匹配发生时要调用的函数关联的表达式列表。这些函数可能是来自各种对象的方法,这当然会导致借用检查器抱怨。这是我想要的示例:

use std::collections::HashMap;

struct Foo(bool);

impl Foo {
    fn say(&self) {
        println!("I'm {}", self.0);
    }
    fn morph(&mut self) {
        self.0 = !self.0;
    }
}

fn main() {
    let mut foo = Foo(true);

    let mut routes: HashMap<String, Box<FnMut()>> = HashMap::new();
    routes.insert("foo/say".to_string(), Box::new(|| foo.say()));  //< First (immutable) borrow of foo
    routes.insert("foo/morph".to_string(), Box::new(|| foo.morph())); //< Second (mutable) borrow of foo
    routes.insert("bar".to_string(), Box::new(|| println!("hello"))); //< Compiler also says immutable foo is used here
}

我理解为什么借用检查器对此不满意,但是我想知道在 Rust 中实现它的惯用方式是什么

旁注:任何关于获得 list/array/hashmap 或任何异构函数集合的最佳方法的一般性评论将不胜感激。

解决方案非常简单,真的。因为您将需要一个允许您按需获得可变借用的结构,所以您将需要 RwLock。因为我猜你正在构建的是一个 HTTP 路由器,为了绕过 Foo 的生命周期要求,你会想要将 RwLock 包装在 Arc 中,比如所以:

use std::collections::HashMap;
use std::sync::{Arc, RwLock};

struct Foo(bool);

impl Foo {
    fn say(&self) {
        println!("I'm {}", self.0);
    }
    fn morph(&mut self) {
        self.0 = !self.0;
    }
}

fn main() {
    let mut foo = Arc::new(RwLock::new(Foo(true)));

    let mut routes: HashMap<String, Box<FnMut()>> = HashMap::new();
    routes.insert("foo/say".to_string(), Box::new(|| foo.read().unwrap().say()));  //< First (immutable) borrow of foo
    routes.insert("foo/morph".to_string(), Box::new(|| foo.write().unwrap().morph())); //< Second (mutable) borrow of foo
    routes.insert("bar".to_string(), Box::new(|| println!("hello"))); //< Compiler also says immutable foo is used here
}

请注意,我滥用了这样一个事实,即一切都可以借用 foo 只读。如果你需要 move 闭包中的东西,Arc 实现 Clone,所以你绝对应该利用它。

其余的很好 - 只要您的闭包都具有相同的签名,将它们装箱并将它们存储在任何集合中是惯用的。