为什么.or_else()被公式化两次?

bri*_*tar 0 error-handling rust

Result文档给出了下面的解释.or_else()方法:

fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F>

如果结果是Err则调用op,否则返回self的Ok值.

此功能可用于基于结果值的控制流程.

例子

fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }

fn err(x: u32) -> Result<u32, u32> { Err(x) }

assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));

assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));

assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));

assert_eq!(Err(3).or_else(err).or_else(err), Err(3));

认为可以or_else用更多的空格解析类型注释:

fn or_else<F,                           // F being the return type of the Result?
           O: FnOnce(E) -> Result<T, F> // the function to run instead if error
          > 
           (self, op: O)                // arguments to the `.or_else()` method
-> Result<T, F>                         // return type is again Result
Run Code Online (Sandbox Code Playgroud)

假设我有这个权利,这是否意味着.or_else()只是给你一个ResultError用的返回值替换op功能?

我可以理解Result再次返回,因为可能错误抛出的代码下游的所有代码都被"染色",可能会有进一步的错误(并且由调用者来处理).但为什么在例子中加倍调用呢?有几种不同的排列,但我不确定他们试图展示的是什么(或者这种加倍的or_else()模式是不是惯用的).

vir*_*tor 8

这个例子可能有点不幸,因为它试图同时显示如何or_else工作,以及为什么要使用它.

将它分成两部分.首先,or_else实际做了什么.如果你在Ok值上调用它,它会传递Ok值.如果在Err值上调用它,它将执行该函数.这个例子应该足够了:

Ok(2).or_else(sq), Ok(2) // not called
Ok(2).or_else(err), Ok(2) // not called
Err(2).or_else(sq), Ok(4) // called, succeeds
Err(2).or_else(err), Err(3) // called, fails
Run Code Online (Sandbox Code Playgroud)

现在,你为什么要使用它的一部分.想象一下,你正在做一些有很多替代方法的操作.例如,你正在尝试在linux上安装一些软件包,但不关心哪个软件包管理器可用 - 你只是要强制它.返回所有函数后,Result<...>您可以执行以下操作:

install_with_apt().
    or_else(install_with_yum).
    or_else(install_with_pacman).
    or_else(install_with_dnf).
    or_else...
Run Code Online (Sandbox Code Playgroud)

你会知道,如果你回来了Ok,至少有一个成功了,如果你回来了,Err所有这些都失败了..or_else()如果可能只是尝试向您展示,示例中的双倍使用可以轻松地链接此调用.