如何从包含未来的结果创建未来?

all*_*y87 7 future rust

是否有可能(合乎逻辑?)将包含未来的结果转换为解决结果的未来?

以下功能有点损坏,但希望能让我想要实现的目标更加清晰:

use std::future::Future;

fn transpose<T,U,E>(result: Result<T,E>) -> impl Future<Output = Result<U, E>>
   where T: Future<Output = Result<U,E>> /* not sure if this is the correct trait bound */ {
   match result {
      Ok(inner) => /* a future that eventually resolves to a Result<U, E> */
      Err(error) => /* a future that immediately resolves to a Result<U, E>::Err(error) */
   }
}
Run Code Online (Sandbox Code Playgroud)

给出一些上下文:在async从传递给 的闭包中调用函数后,我发现自己需要这样做Result::map,所以也许这是我的第一个错误。

tre*_*tcl 3

也许人们通常想要的是立即处理这种Err情况,而不是等到未来被.await编辑,所以这可以解释为什么这样的函数还不存在。async但是,如果您确实需要它,使用and编写非常简单.await

fn transpose_flatten<T, U, E>(result: Result<T, E>) -> impl Future<Output = Result<U, E>>
where
    T: Future<Output = Result<U, E>>,
{
    async {                          // when polled,
        match result {
            Ok(good) => good.await,  // defer to the inner Future if it exists
            Err(bad) => Err(bad),    // otherwise return the error immediately
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或者使用相同的东西async fn(并不总是完全相同的东西,但在这种情况下似乎是):

async fn transpose_flatten<T, U, E>(result: Result<T, E>) -> Result<U, E>
where
    T: Future<Output = Result<U, E>>,
{
    match result {
        Ok(good) => good.await,
        Err(bad) => Err(bad),
    }
}
Run Code Online (Sandbox Code Playgroud)

由于该Err值是从封闭的async块或函数返回的,因此您可以使用?语法使其更短:

async fn transpose_flatten<T, U, E>(result: Result<T, E>) -> Result<U, E>
where
    T: Future<Output = Result<U, E>>,
{
    result?.await
}
Run Code Online (Sandbox Code Playgroud)

我调用这个函数是transpose_flatten因为对我来说transpose听起来它应该采用Result<Future<Output = U>, _>. 该函数展平了两层Result(传递给函数的一层和从 future 返回的一层)。