将结果上的迭代器转换为结果<Vec<_>,_>



我正试图编写一个函数,将glob的输出Result<Paths, PatternError>转换为Result<Vec<PathBuf>, Error>。我有自己的Error类型,它为glob::GlobErrorglob::PatternError实现From。目前我已经实现了以下功能:

fn glob_abs_path(fpath: &str) -> Result<Vec<PathBuf>, Error> {
Ok(glob(fpath)?.map(|val| val.unwrap()).collect::<Vec<_>>())
}

我正在寻找一种方法来删除对val.unwrap的调用,并允许在遇到GlobError时返回。我尝试使用collect::<Result<Vec<_>>>()?,但没有成功。

如果问题标题含糊不清,请道歉。我是个新手,还不熟悉简明地表达这个问题。

这里有几个问题:

fn glob_abs_path(fpath: &str) -> std::result::Result<Vec<PathBuf>, Error> {
Ok(glob(fpath)?.map(|val| val.unwrap()).collect::<Vec<_>>())
}

glob_abs_path结束时,您正在将值收集到Vec中。如果您尝试在vec上使用?运算符,它将失败:

error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
--> src/lib.rs:26:8
|
26 |     Ok(glob(fpath)?.map(|val| val.unwrap()).collect::<Vec<_>>()?)
|        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied 
to type `std::vec::Vec<std::result::Result<std::path::PathBuf, glob::GlobError>>`

?运算符只能应用于实现std::ops::Try的值,即Result<_, _>。因此,我们要做的是将迭代器收集到Result:中

fn glob_abs_path(fpath: &str) -> std::result::Result<Vec<PathBuf>, Error> {
Ok(glob(fpath)?.map(|val| val.unwrap()).collect::<std::result::Result<Vec<_>, _>>()?)
}

然而,我们在这里得到了另一个错误:

error[E0277]: a value of type `std::result::Result<std::vec::Vec<_>, _>` cannot be built 
from an iterator over elements of type `std::path::PathBuf`
--> src/lib.rs:26:43
|
26 |   Ok(glob(fpath)?.map(|val| val.unwrap()).collect::<std::result::Result<Vec<_>, _>>())
|                                           ^^^^^^^ value of type 
|  `std::result::Result<std::vec::Vec<_>, _>` cannot be built from 
|  `std::iter::Iterator<Item=std::path::PathBuf>`
|

这里的问题是,我们在收集值.map(|val| val.unwrap())之前对其展开,迭代器不知道如何将展开的值(PathBuf(转换为Result。删除打开包装的调用修复了问题:

fn glob_abs_path(fpath: &str) -> std::result::Result<Vec<PathBuf>, Error> {
Ok(glob(fpath)?.collect::<std::result::Result<Vec<_>, _>>()?)
}

代码现在已编译。您提到您有一个Result:的类型别名

type MyResult<T> = std::result::Result<T, Error>

您可以在返回值中使用此类型的别名:

fn glob_abs_path(fpath: &str) -> MyResult<Vec<PathBuf>> {
Ok(glob(fpath)?.collect::<std::result::Result<Vec<_>, _>>()?)
}

但是,当您在中使用它来收集迭代器时:

fn glob_abs_path(fpath: &str) -> MyResult<Vec<PathBuf>> {
Ok(glob(fpath)?.collect::<MyResult<Vec<_>>>()?)
}

失败:

error[E0277]: a value of type `std::result::Result<std::vec::Vec<_>, Error>` 
cannot be built from an iterator over elements of type `std::result::Result<std::path::PathBuf, glob::GlobError>`
--> src/lib.rs:26:21
|
26 |     Ok(glob(fpath)?.collect::<MyResult<Vec<_>>>()?)
|                     ^^^^^^^ value of type `std::result::Result<std::vec::Vec<_>, Error>` 
|  cannot be built from `std::iter::Iterator<Item=std::result::Result<std::path::PathBuf, glob::GlobError>>`
|

这是因为MyResult明确地将返回值声明为您的自定义错误类型。Iterator无法将GlobError转换为您的Error。该转换由?操作员处理:

fn glob_abs_path(fpath: &str) -> MyResult<Vec<PathBuf>> {
Ok(glob(fpath)?.collect::<std::result::Result<Vec<_>, GlobError>>()?)
}

如上所述,迭代器被收集到<std::result::Result<Vec<_>, GlobError>中,然后由?运算符转换为std::result::Result<Vec<_>, YourError>(MyResult(。

这是Rust Playground 的最终工作代码

最新更新