如何存储和使用接受引用并返回未来的可选闭包?
Posted
技术标签:
【中文标题】如何存储和使用接受引用并返回未来的可选闭包?【英文标题】:How to store and use an optional closure that accepts a reference and returns a future? 【发布时间】:2020-10-27 14:26:49 【问题描述】:我有一个异步函数 save
,它有一个 Save
结构作为参数,它可以选择包含一个异步函数 (validator
)。问题是以下代码仅在指定Some(..)
时有效,而None
编译器会抛出错误。
use std::future::Future;
trait SomeTrait
enum SomeError
#[derive(Debug)]
struct User
impl SomeTrait for User
struct Save<T, F>
where
T: SomeTrait,
F: Future<Output = Result<(), SomeError>>,
pub validator: Option<Box<dyn Fn(&T) -> F>>,
async fn save<T, F>(obj: &T, args: Save<T, F>) -> Result<(), SomeError>
where
T: SomeTrait,
F: Future<Output = Result<(), SomeError>>,
if let Some(v) = args.validator
(*v)(obj).await?;
Ok(())
#[tokio::test]
async fn test_func()
let user = User ;
save(&user, Save validator: None ).await;
save(
&user,
Save
validator: Some(Box::new(|obj| async
println!("input: :?", obj);
Ok(())
)),
,
)
.await;
错误:
error[E0698]: type inside `async` block must be known in this context
--> test_utils/src/testin.rs:35:17
|
35 | save(&user, Save validator: None ).await;
| ^^^^ cannot infer type for type parameter `F` declared on the struct `Save`
|
note: the type is part of the `async` block because of this `await`
--> test_utils/src/testin.rs:35:5
|
35 | save(&user, Save validator: None ).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
我怎样才能使上面的代码工作?在Save
结构中是否有不使用F
泛型参数的替代实现?我现在可以使用它,但是当Save
结构中有多个函数时可能会变得笨拙。
【问题讨论】:
"异步闭包不稳定" — 如果您使用不稳定的功能,您必须注意您使用的是哪个夜间版本。如果您没有使用夜间编译器,那么您就没有使用异步闭包。请edit澄清您的问题。 另见What is the difference between|_| async move
and async move |_|
; What's the difference of lifetime inference between async fn and async closure?
另见How to accept an async function as an argument?; How to indicate that the lifetime of an async function's return value is the same as a parameter?.
感谢您的反馈!我正在阅读您现在引用的页面,并将很快更新我的问题
我认为我的情况因使用了Option而有所不同,只有在使用None
时才会出现问题。
【参考方案1】:
使用BoxFuture
由于您想隐藏类型,因此使用 trait 对象很有用。 BoxFuture
非常适合这个,结合boxed
方法来创建它:
use futures::future::BoxFuture, FutureExt;
struct Save<T>
where
T: SomeTrait,
pub validator: Option<Box<dyn Fn(&T) -> BoxFuture<Result<(), SomeError>>>>,
let _ = save(
&user,
Save
validator: Some(Box::new(|obj|
async move
println!("input: :?", obj);
Ok(())
.boxed()
)),
,
)
.await;
另见:
How can one await a result of a boxed future? Cannot use `impl Future` to store async function in a vector How do I erase the type of future in the new future API?对泛型类型使用 None
这里的问题是必须知道泛型类型,即使您没有使用它,因为您选择了None
。您可以提供适合约束的类型(实现 Future
,Output
是 Result<(), SomeError>
)。这里我使用Ready
:
type Dummy = futures::future::Ready<Result<(), SomeError>>;
save::<_, Dummy>(&user, Save validator: None ).await;
不幸的是,这会产生一个我还不知道如何解决的错误(“借来的数据不能存储在它的闭包之外”)。
另见:
Create a generic struct with Option<T> without specifying T when instantiating with None Pass None into a function that accepts Option Is there a way to hint to the compiler to use some kind of default generic type when using Option::None?【讨论】:
以上是关于如何存储和使用接受引用并返回未来的可选闭包?的主要内容,如果未能解决你的问题,请参考以下文章