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
,所以你绝对应该利用它。
其余的很好 - 只要您的闭包都具有相同的签名,将它们装箱并将它们存储在任何集合中是惯用的。
我正在尝试用 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
,所以你绝对应该利用它。
其余的很好 - 只要您的闭包都具有相同的签名,将它们装箱并将它们存储在任何集合中是惯用的。