简体   繁体   English

如何根据作为参数传递的闭包的返回类型来更改 function 的行为?

[英]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();

Playground 操场

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.

相关问题 如何指定闭包参数的类型? - How can I specify the type of a closure argument? 是否可以将带有引用的函数作为提供自有值的闭包参数传​​递? - Can a function that takes a reference be passed as a closure argument that will provide owned values? 如何从闭包中返回对闭包参数的引用? - How do I return a reference to a closure's argument from the closure? 当函数需要引用闭包参数时,如何使用函数作为闭包? - How can I use a function as a closure when the function needs to take a reference to the closures argument? 如何解决传递给闭包的 &amp;PathBuf 的冲突生命周期要求? - How can I solve conflicting lifetime requirements for a &PathBuf passed to a closure? 在 Rust 中返回一个返回函数参数的闭包 - Return a closure returning the function argument in Rust 如何更改此功能的返回类型? - How can I change the return type of this function? rust 中函数接受闭包作为参数或返回闭包的惯用方式是什么? - What is the idiomatic way in rust for a function accepts a closure as argument or return a closure? 如何在 Rust 中创建作为参数传递给 function 的任何类型的新对象 - How to create new objects of any type that is passed as an argument to a function in Rust 存储称为内部闭包的 function 的返回类型 - Storing the return type of function called inside closure
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM