当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。