是否可以(逻辑?(将包含未来的结果转换为解析为结果的未来?
以下功能有点坏,但希望能让我试图实现的目标更加清晰:
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) */
}
}
为了提供一些上下文:在从传递给Result::map
的闭包中调用async
函数后,我发现自己需要这样做,所以这可能是我的第一个错误。
可能人们通常想要的是立即处理Err
的情况,而不是等到将来是.await
,所以这可能解释了为什么这样的函数还不存在。然而,如果您确实需要它,那么使用async
和.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
}
}
}
或者使用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),
}
}
由于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
}
我之所以调用这个函数transpose_flatten
,是因为对我来说,transpose
听起来应该使用Result<Future<Output = U>, _>
。此函数使Result
的两层变平(传递给函数的一层和将来返回的一层(。
如果result
是Ok
,您可以简单地返回内部未来。但是,如果它是Err
,则必须构造一个新的将来解析为Result<U, E>::Err(e)
。这意味着您不能返回泛型Future
,因为两个match
臂返回两个不同的类型。你必须返回一个特征对象:
fn transpose<T, E: 'static, U: 'static>(result: Result<T, E>) -> Box<dyn Future<Output = Result<U, E>>>
where T: Future<Output = Result<U, E>> + 'static {
match result {
Ok(inner) => Box::new(inner),
Err(error) => Box::new(async { Err(error) })
}
}