本文簡要介紹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 TryIter用法及代碼示例
- Rust Try.from_output用法及代碼示例
- Rust TryFrom用法及代碼示例
- Rust Try.branch用法及代碼示例
- Rust TcpStream.local_addr用法及代碼示例
- Rust TcpStream.peer_addr用法及代碼示例
- Rust TcpListener.take_error用法及代碼示例
- Rust Take.limit用法及代碼示例
- Rust TcpStream.set_nodelay用法及代碼示例
- Rust ToSocketAddrs用法及代碼示例
- Rust TcpStream.nodelay用法及代碼示例
- Rust ToOwned.to_owned用法及代碼示例
- Rust TcpListener.into_incoming用法及代碼示例
- Rust TcpStream.take_error用法及代碼示例
- Rust TcpListener.accept用法及代碼示例
- Rust ThreadId用法及代碼示例
- Rust Take.set_limit用法及代碼示例
- Rust Thread.unpark用法及代碼示例
- Rust TcpStream.write_timeout用法及代碼示例
- Rust TcpListener.local_addr用法及代碼示例
- Rust Take.get_ref用法及代碼示例
- Rust TcpStream.peek用法及代碼示例
- Rust TcpStream.set_write_timeout用法及代碼示例
- Rust TcpListener.ttl用法及代碼示例
- Rust TcpStream.set_nonblocking用法及代碼示例
注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Trait std::ops::Try。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。