當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Rust Try用法及代碼示例


本文簡要介紹rust語言中 Trait std::ops::Try 的用法。

用法

pub trait Try: FromResidual<Self::Residual> {
    type Output;
    type Residual;
    fn from_output(output: Self::Output) -> Self;
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}

? 運算符和try {} 塊。

try_* 方法通常涉及實現此特征的類型。例如,傳遞給 Iterator::try_fold Iterator::try_for_each 的閉包必須返回這樣的類型。

Try 類型通常是那些包含兩個或更多類別值的類型,其中一些子集通常通過早期返返回處理,因此值得提供一種簡潔(但仍然可見)的語法來簡化它。

這在使用 Result Option 進行錯誤處理時最常見。此特征的典型實現在 ControlFlow 上。

在通用代碼中使用Try

Iterator::try_fold 在 Rust 1.27 中被穩定回調,但這個特性要更新得多。為了說明各種關聯的類型和方法,讓我們實現我們自己的版本。

提醒一下,一個可靠的折疊版本看起來像這樣:

fn simple_fold<A, T>(
    iter: impl Iterator<Item = T>,
    mut accum: A,
    mut f: impl FnMut(A, T) -> A,
) -> A {
    for x in iter {
        accum = f(accum, x);
    }
    accum
}

因此,不是 f 隻返回一個 A ,我們需要它返回一些在“不要短路”路徑中產生 A 的其他類型。方便的是,這也是我們需要從函數返回的類型。

讓我們為該類型添加一個新的通用參數R,並將其綁定到我們想要的輸出類型:

fn simple_try_fold_1<A, T, R: Try<Output = A>>(
    iter: impl Iterator<Item = T>,
    mut accum: A,
    mut f: impl FnMut(A, T) -> R,
) -> R {
    todo!()
}

如果我們通過整個迭代器,我們需要使用 Try::from_output 將累加器包裝成返回類型:

fn simple_try_fold_2<A, T, R: Try<Output = A>>(
    iter: impl Iterator<Item = T>,
    mut accum: A,
    mut f: impl FnMut(A, T) -> R,
) -> R {
    for x in iter {
        let cf = f(accum, x).branch();
        match cf {
            ControlFlow::Continue(a) => accum = a,
            ControlFlow::Break(_) => todo!(),
        }
    }
    R::from_output(accum)
}

我們還需要 FromResidual::from_residual 將殘差轉回原始類型。但是因為它是 Try 的超特征,我們不需要在界限內提及它。所有實現 Try 的類型都可以從它們對應的殘差中重新創建,所以我們就稱之為:

pub fn simple_try_fold_3<A, T, R: Try<Output = A>>(
    iter: impl Iterator<Item = T>,
    mut accum: A,
    mut f: impl FnMut(A, T) -> R,
) -> R {
    for x in iter {
        let cf = f(accum, x).branch();
        match cf {
            ControlFlow::Continue(a) => accum = a,
            ControlFlow::Break(r) => return R::from_residual(r),
        }
    }
    R::from_output(accum)
}

但是這個“調用branch,然後調用match,如果是Break,則調用return”正是?操作符內部發生的事情。因此,我們可以使用 ? 代替手動完成所有這些操作:

fn simple_try_fold<A, T, R: Try<Output = A>>(
    iter: impl Iterator<Item = T>,
    mut accum: A,
    mut f: impl FnMut(A, T) -> R,
) -> R {
    for x in iter {
        accum = f(accum, x)?;
    }
    R::from_output(accum)
}

相關用法


注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Trait std::ops::Try。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。