代码之家  ›  专栏  ›  技术社区  ›  xehpuk

如果某个选项是某个,则返回Err的惯用方法

  •  1
  • xehpuk  · 技术社区  · 4 年前

    我们可以用 or_else ? 返回 Err None :

    let o = None;
    let x = o.ok_or(666)?;
    

    Some :

    let o = Some(42);
    if o.is_some() {
        return Err(666);
    }
    

    我们能用这种方法吗 ? 也?

    2 回复  |  直到 4 年前
        1
  •  2
  •   vallentin Remi    4 年前

    我假设这是所有关于它是一个单行和保存字符。

    你可以用 map_or() Some(_) 进入之内 Err(666) None Ok(()) . 然而,这不是惯用的,我个人也会坚持 if is_some() { return Err(666); } ,因为这样做对读者来说更清楚。

    fn foo(o: Option<i32>) -> Result<(), i32> {
        o.map_or(Ok(()), |_| Err(666))?;
    
        Ok(())
    }
    
    fn main() {
        println!("{:?}", foo(None));
        println!("{:?}", foo(Some(42)));
    }
    

    输出:

    Ok(())  
    Err(666)
    

    你也可以创建自己的 ErrOnSome err_on_some() 即使不知道系统的实现,读者也能更清楚地理解正在发生的事情 出错() 方法。

    trait ErrOnSome {
        fn err_on_some<F, E>(&self, f: F) -> Result<(), E>
        where
            F: FnOnce() -> Result<(), E>;
    }
    
    impl<T> ErrOnSome for Option<T> {
        fn err_on_some<F, E>(&self, f: F) -> Result<(), E>
        where
            F: FnOnce() -> Result<(), E>,
        {
            match self {
                None => Ok(()),
                Some(_) => f(),
            }
        }
    }
    
    fn foo(o: Option<i32>) -> Result<(), i32> {
        o.err_on_some(|| Err(666))?;
    
        Ok(())
    }
    

    使用相同的 main()


    编辑: Option

    如果包含的值是原语,即便宜到 创造 ,然后你就可以坚持 xor() . 然而,这不是惯用的,我个人也会坚持 if is_some(){return Err(666);}

    fn foo(o: Option<i32>) -> Option<()> {
        o.xor(Some(666))?;
    
        Some(())
    }
    
    fn main() {
        println!("{:?}", foo(None));
        println!("{:?}", foo(Some(42)));
    }
    

    输出:

    Some(123)
    None
    
        2
  •  1
  •   user4815162342    4 年前

    我们能不能回来 Err Some ]与 ? 也?

    我不会叫它 惯用的 ,但您可以使用 Option::map 绘制地图 一些 将选项的变体转换为 . 这将改变 Option<T> Option<Result<X, E>> Result<Option<X>, E> 使用 ?

    fn x() -> Result<(), i32> {
        let o = Some(42);
        o.map(|_| Err::<(), _>(666)).transpose()?;
        Ok(())
    }
    

    大菱鲆 提供必要的类型提示,因为否则Rust无法确定 X 属于 Result<X, E> 并且结果必须同时具有ok和error类型。我选择了 () ,但这与 () 函数的返回类型;可能是其他类型的因为 Result .