rust 从Result< T,T>获取值T

fhg3lkii  于 2023-05-18  发布在  其他
关注(0)|答案(3)|浏览(199)

我有一个函数:

fn foo<i32>(x: i32) -> Result<i32, i32> {
    ...
}

我想把结果的值提取到一个变量中,不管它是Ok还是Err。我可以这样做:

let val = match foo(10) {
    Ok(i) => i,
    Err(i) => i,
}

想知道是否有一个“更干净”或更“习惯”的方法来这样做,或者这是最好的方法。

**注意:**用例用于二进制搜索,其中我有一个通用函数,如果找到匹配,则返回Ok(i)和索引,否则返回Err(i)和索引,您将插入目标以保持数组排序。但是,我不想公开这个通用函数,而是公开两个变体binary_searchbinary_search_insert_index。对于第一个,我只返回i if Ok(i) else None。对于第二个,我只是返回i无论如何。

zzlelutf

zzlelutf1#

我最近发现了这个宝石:

let (Ok(my_var)|Err(my_var)) = foo(5);
// Can use `my_var` here.
kkbh8khc

kkbh8khc2#

您可以使用以下模式:

fn unwrap_either<T>(result: Result<T, T>) -> T {
    result.unwrap_or_else(|e| e)
}
wr98u20j

wr98u20j3#

没有内置的实用程序方法可以完全做到这一点;我会说你提供的比赛是完全可以接受的。
如果你经常使用这个模式,你可以在Result上实现你自己的扩展:

trait ResultUnwrapEitherExt {
    type Value;
    
    fn unwrap_either(self) -> Self::Value;
}

impl<T> ResultUnwrapEitherExt for Result<T, T> {
    type Value = T;
    
    fn unwrap_either(self) -> T {
        match self {
            Ok(v) => v,
            Err(v) => v,
        }
    }
}

现在你在任何地方use这个trait,你可以简单地做foo(10).unwrap_either()
作为旁注,the discriminant is not checked when compiled with optimizations(例如在释放模式中),因为它是冗余检查。对于OkErr变体,有效载荷存储在相同的位置,因此优化器将发出简单地获取该位置的值的代码,完全忽略判别式。

相关问题