本文简要介绍rust语言中 Trait core::ops::Try
的用法。
用法
pub trait Try: FromResidual {
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 Try用法及代码示例
- 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-lang.org大神的英文原创作品 Trait core::ops::Try。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。