[英]How can I alter the behavior of a function based on the return type of a closure passed as an argument?
I have a function that returns the result of a curried function:我有一个 function 返回咖喱 function 的结果:
async fn runit<F, Fut, Ret>(cb: F) -> Result<Ret, MyError>
where
F: FnOnce() -> Fut,
Fut: Future<Output = Ret>,
{
Ok(cb().await)
}
Sometimes F
may return a Result<Ret, MyError>
, requiring the caller to unwrap the returned value twice.有时F
可能会返回一个Result<Ret, MyError>
,要求调用者将返回的值解包两次。 Is there a way I can write this such that the function automatically detects whether F
already returns the right type and avoids the call to Ok
?有没有一种方法可以让 function 自动检测F
是否已经返回正确的类型并避免调用Ok
?
You might be able to use a trait with separate blanket implementations for Result
and other types.您也许可以将 trait 与Result
和其他类型的单独一揽子实现一起使用。 Something like:就像是:
pub trait IntoResult<T, E> {
fn into_result(self) -> Result<T, E>;
}
impl<T, E> IntoResult<T, E> for Result<T, E> {
fn into_result(self) -> Result<T, E> {
self
}
}
impl<T, E> IntoResult<T, E> for T {
fn into_result(self) -> Result<T, E> {
Ok(self)
}
}
Then you can implement runit
to call into_result()
:然后你可以实现runit
来调用into_result()
:
async fn runit<F, Fut, Ret, RawRet>(cb: F) -> Result<Ret, MyError>
where
F: FnOnce() -> Fut,
Fut: Future<Output = RawRet>,
RawRet: IntoResult<Ret, MyError>,
{
cb().await.into_result()
}
Now Rust will be able to infer Ret
that satisfies the IntoResult
trait, effectively eliminating the inner Result
:现在 Rust 将能够推断出满足IntoResult
特征的Ret
,有效地消除了内部Result
:
// one unwrap needed for Result<usize, MyError>
let _x: usize = runit(|| async { 1 }).await.unwrap();
// two unwraps needed because closure returns Result whose error is not MyError
let _y: usize = runit(|| async { Ok::<_, std::io::Error>(1usize) })
.await
.unwrap()
.unwrap();
// one unwrap enough because closure returns Result<usize, MyError>
let _z: usize = runit(|| async { Ok::<_, MyError>(1usize) }).await.unwrap();
Before using this in production, I suggest being very careful with this kind of "cleverness".在生产中使用它之前,我建议对这种“聪明”非常小心。 While it looks really nice when it works, it can complicate the signatures of functions and sometimes it can require type hints that would otherwise not be necessary.虽然它在工作时看起来非常好,但它会使函数的签名复杂化,有时它可能需要类型提示,否则就不需要了。 It is often simpler to use something like anyhow::Error
to coalesce results of incompatible errors into one result.使用类似anyhow::Error
的方法将不兼容错误的结果合并为一个结果通常更简单。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.