从Rust中的函数返回异步函数

从Rust中的函数返回异步函数,rust,async-await,Rust,Async Await,第1部分:返回异步函数的函数的签名应该是什么 pub async fn一些异步函数(arg:&str){ //这里应该是什么? 发布fn更高阶函数(操作:&str)->??? { 一些异步函数 } 第2部分:如果基于action参数,高阶函数必须返回async函数1或async函数2,那么sig应该是什么 如果存在多个解决方案,我也有兴趣了解性能权衡。请注意,我希望将函数本身作为fn指针或fn*特征返回,而不是调用它的结果。返回函数 返回实际函数指针需要堆分配和包装器: 使用std::futu

第1部分:返回异步函数的函数的签名应该是什么

pub async fn一些异步函数(arg:&str){
//这里应该是什么?
发布fn更高阶函数(操作:&str)->???
{
一些异步函数
}
第2部分:如果基于action参数,高阶函数必须返回async函数1或async函数2,那么sig应该是什么

如果存在多个解决方案,我也有兴趣了解性能权衡。请注意,我希望将函数本身作为fn指针或fn*特征返回,而不是调用它的结果。

返回函数 返回实际函数指针需要堆分配和包装器:

使用std::future::future;
使用std::pin::pin;
pub async fn some_async_func(arg:&str){
pub fn某些异步函数包装器Pin(操作:&str)
->fn(&'a str)->Pin impl Future+'a
,但这需要编译器进行更多的猜测,目前不受支持

如果您同意使用
Fn
而不是
Fn
,则可以去掉包装器:

pub async fn some_async_func(arg: &str) {}

pub fn higher_order_func<'a>(action: &str)
    -> impl Fn(&'a str) -> Pin<Box<dyn Future<Output=()> + 'a>>
{
    |arg: &'a str| {
        Box::pin(some_async_func(arg))
    }
}
备选方案:回归未来

为了简化事情,考虑返回未来本身而不是函数指针。这实际上是相同的,但更好,并且不需要堆分配:

pub async fn一些异步函数(arg:&str){
pub fn高阶函数func future impl future+'a
{
一些异步函数(arg)
}
当调用
higher\u order\u func\u future
时,可能会出现这样的情况,
some\u async\u func
正在执行,但情况并非如此。由于异步函数的工作方式,当您调用
某些\u async\u func
时,不会执行任何用户代码。函数调用返回一个
未来
:只有当有人等待返回的未来时,才会执行实际的函数体

新函数的使用方法与前一个函数几乎相同:

//高阶函数返回函数指针
异步fn my_函数(){
让行动=“一”;
让arg=“你好”;
高阶函数(动作)(参数)。等待;
}
//高阶函数返回未来
异步fn my_函数(){
让行动=“一”;
让arg=“你好”;
高阶函数未来(动作,参数)。等待;
}
再次请注意,在这两种情况下,实际的
某些_async_func
主体仅在等待未来时执行

如果您希望能够基于
操作
值调用不同的异步函数,则需要再次装箱:

pub async fn一些异步函数(arg:&str){
pub async fn一些异步函数(arg:&str){

pub fn higher\u order\u func\u future pin答案调用函数并返回结果,而不是返回函数本身。我想返回一个函数指针(函数项也可以)。编辑了答案。最有可能的是,您并不真正需要函数指针;如果您确信您确实这样做了,请分享您的用例详细信息。谢谢您的精彩回答。我试图从另一种语言移植一些模式,这涉及到发回指针。我可以修改它们以使用未来,但我也想了解如何做到这一点。您的帖子内容丰富,对这两方面都有很大帮助。当调用的时间重要时,或者当调用高阶函数创建某些局部状态时(例如,当高阶函数将异步函数的结果缓存一段时间时),您会遇到想要返回异步函数的情况(由函数的结果决定,因此不能只执行带有超时的标准选择)。