如何存储和使用接受引用和 returns 未来的可选闭包?
How to store and use an optional closure that accepts a reference and returns a future?
我有一个异步函数 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
结构中有多个函数时可能会变得笨拙。
使用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;
另请参阅:
将 None 与通用类型一起使用
这里的问题是泛型类型必须是已知的,即使您因为选择了 None
而没有使用它也是如此。您可以提供符合约束条件的类型(实现 Future
、Output
是 Result<(), SomeError>
)。这里我使用 Ready
:
type Dummy = futures::future::Ready<Result<(), SomeError>>;
save::<_, Dummy>(&user, Save { validator: None }).await;
不幸的是,这会产生一个我还不知道如何解决的错误(“借用的数据不能存储在其闭包之外”)。
另请参阅:
我有一个异步函数 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
结构中有多个函数时可能会变得笨拙。
使用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;
另请参阅:
将 None 与通用类型一起使用
这里的问题是泛型类型必须是已知的,即使您因为选择了 None
而没有使用它也是如此。您可以提供符合约束条件的类型(实现 Future
、Output
是 Result<(), SomeError>
)。这里我使用 Ready
:
type Dummy = futures::future::Ready<Result<(), SomeError>>;
save::<_, Dummy>(&user, Save { validator: None }).await;
不幸的是,这会产生一个我还不知道如何解决的错误(“借用的数据不能存储在其闭包之外”)。
另请参阅: