簡體   English   中英

如何根據作為參數傳遞的閉包的返回類型來更改 function 的行為?

[英]How can I alter the behavior of a function based on the return type of a closure passed as an argument?

我有一個 function 返回咖喱 function 的結果:

async fn runit<F, Fut, Ret>(cb: F) -> Result<Ret, MyError>
where
    F: FnOnce() -> Fut,
    Fut: Future<Output = Ret>,
{
    Ok(cb().await)
}

有時F可能會返回一個Result<Ret, MyError> ,要求調用者將返回的值解包兩次。 有沒有一種方法可以讓 function 自動檢測F是否已經返回正確的類型並避免調用Ok

您也許可以將 trait 與Result和其他類型的單獨一攬子實現一起使用。 就像是:

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)
    }
}

然后你可以實現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()
}

現在 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();

操場

在生產中使用它之前,我建議對這種“聰明”非常小心。 雖然它在工作時看起來非常好,但它會使函數的簽名復雜化,有時它可能需要類型提示,否則就不需要了。 使用類似anyhow::Error的方法將不兼容錯誤的結果合並為一個結果通常更簡單。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM