我正试图编写一个函数,将glob的输出Result<Paths, PatternError>
转换为Result<Vec<PathBuf>, Error>
。我有自己的Error
类型,它为glob::GlobError
和glob::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 的最终工作代码