如何在Rust中将异步函数放入地图中? [英] How can I put an async function into a map in Rust?
问题描述
为hyper
编写异步路由器时,我无法处理异步功能.
I cannot handle async functions when writing an async router for hyper
.
此代码:
use std::collections::HashMap;
use std::future::Future;
type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32, i32) -> dyn Future<Output = BoxedResult<i32>>>;
async fn add(a: i32, b: i32) -> BoxedResult<i32> {
Ok(a + b)
}
async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
Ok(a - b)
}
fn main() {
let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(add));
map.insert("sub", Box::new(sub));
println!("map size: {}", map.len());
}
生成以下编译器错误:
error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {add} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
--> src/main.rs:17:23
|
17 | map.insert("add", Box::new(add));
| ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
|
= note: expected type `impl std::future::Future`
found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
= note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
error[E0271]: type mismatch resolving `<fn(i32, i32) -> impl std::future::Future {sub} as std::ops::FnOnce<(i32, i32)>>::Output == dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
--> src/main.rs:18:23
|
18 | map.insert("sub", Box::new(sub));
| ^^^^^^^^^^^^^ expected opaque type, found trait std::future::Future
|
= note: expected type `impl std::future::Future`
found type `dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
= note: required for the cast to the object type `dyn std::ops::Fn(i32, i32) -> dyn std::future::Future<Output = std::result::Result<i32, std::boxed::Box<dyn std::error::Error + std::marker::Send + std::marker::Sync>>>`
impl Future
和dyn Future
之间似乎存在冲突,但是我不知道如何处理.
It seems there is a conflict between impl Future
and dyn Future
, but I have no idea how to handle it.
推荐答案
之所以会发生这种情况,是因为impl Future
是具体的唯一类型,而dyn Future
是抽象类型. HashMap
需要抽象类型,因为它只能容纳单个类型的实例.
This happens because impl Future
is a concrete unique type while dyn Future
is an abstract type. HashMap
expects the abstract type since it can only hold instances of a single type.
如果我们可以对异步函数的返回类型进行装箱,则可以将这些期货添加到HashMap
中.
If we can box the return type of the async functions, we will able to add these futures into a HashMap
.
首先,我们需要更改CalcFn
的类型:
First we need to change the type of CalcFn
:
type CalcFn = Box<dyn Fn(i32, i32) -> Pin<Box<dyn Future<Output = i32>>>>;
然后这可以解决问题:
let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(|a, b| Box::pin(add(a, b))));
map.insert("sub", Box::new(|a, b| Box::pin(sub(a, b))));
println!("map size: {}", map.len());
//map.get("add").unwrap()(2, 3).await
此完整示例
简化的Future
的Item
类型,使用i32
而不是Result
.请另外检查针对您的案例的完整代码.
This complete example
simplified Future
's Item
type, using an i32
instead of a Result
. Please also check the full code for your case.
这篇关于如何在Rust中将异步函数放入地图中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!