Error handling 当使用带有易出错映射函数的filter_map时,如何在错误上聚合迭代器?
假设我想读取目录中的所有文件。我可以这样定义一个函数:Error handling 当使用带有易出错映射函数的filter_map时,如何在错误上聚合迭代器?,error-handling,rust,iterator,Error Handling,Rust,Iterator,假设我想读取目录中的所有文件。我可以这样定义一个函数: use std::error::Error; use std::fs; use std::io; type Result<T> = std::result::Result<T, Box<dyn Error>>; fn read_entry(entry: io::Result<fs::DirEntry>) -> Result<Option<String>> {
use std::error::Error;
use std::fs;
use std::io;
type Result<T> = std::result::Result<T, Box<dyn Error>>;
fn read_entry(entry: io::Result<fs::DirEntry>) -> Result<Option<String>> {
let entry = entry?;
if entry.file_type()?.is_file() {
Ok(Some(fs::read_to_string(entry.file_name())?))
} else {
Ok(None)
}
}
使用std::error::error;
使用std::fs;
使用std::io;
类型Result=std::Result::Result;
fn read_条目(条目:io::Result)->Result{
让进入=进入?;
如果entry.file_type()?.is_file(){
Ok(一些(fs::read_to_string(entry.file_name())?)
}否则{
Ok(无)
}
}
然后试着用它
use std::path::Path;
fn read_all(dir: &Path) -> Result<Vec<String>> {
Ok(fs::read_dir(dir)?
.filter_map(|entry| read_entry(entry).unwrap())
.collect())
}
使用std::path::path;
fn read_all(目录:&路径)->结果{
好的(fs::读取目录(dir)?
.filter_map(| entry | read_entry(entry).unwrap())
.collect())
}
这可以编译,但它只是unwrap()
s错误collect()
通常可以在错误上聚合迭代器,但我不太明白如何使用filter\u map()
实现这一点。我怎样才能解决这个问题
对于Iter
(这是Iterator::collect
的一个基本特征),迭代器中有一个很好的FromIterator
,因此它可以工作:
fn读取所有(目录和路径)->结果{
读目录(dir)?
.filter_map(| entry | read_entry(entry).transpose())
.collect()
}
对于Iter
(这是Iterator::collect
的一个基本特征),有一个很好的from Iterator
,因此它可以工作:
fn读取所有(目录和路径)->结果{
读目录(dir)?
.filter_map(| entry | read_entry(entry).transpose())
.collect()
}
而不是返回结果
您需要选项
,即在:
Ok(Some(T))
:这是一个文件,我们成功地读取了它
确定(无)
:它不是一个文件,但我们没有发现任何错误
Err
:发生错误
之后:
Some(Ok(T))
:这是一个文件,我们成功地读取了它
None
:它不是一个文件,但我们没有发现任何错误
Some(Err)
:发生了一个错误
您可以更改原始实现,但这意味着您不能使用?
运算符,这很糟糕
一个更好的解决方案——正如@Kitsu所指出的那样,使用内置函数将结果
转换为选项
,而不是返回结果
,即,在:
Ok(Some(T))
:这是一个文件,我们成功地读取了它
确定(无)
:它不是一个文件,但我们没有发现任何错误
Err
:发生错误
之后:
Some(Ok(T))
:这是一个文件,我们成功地读取了它
None
:它不是一个文件,但我们没有发现任何错误
Some(Err)
:发生了一个错误
您可以更改原始实现,但这意味着您不能使用?
运算符,这很糟糕
一个更好的解决方案——正如@Kitsu所指出的那样,使用内置函数将结果
转换为选项
只是为了完成,而读取条目
失败的原因是因为使用了条目.file\u name()
而不是条目.path()
因此:
Ok(Some(fs::read_to_string(entry.file_name())?))
应该是:
Ok(Some(fs::read_to_string(entry.path())?))
仅为完成起见,read\u条目
失败的原因是使用了entry.file\u name()
而不是entry.path()
因此:
Ok(Some(fs::read_to_string(entry.file_name())?))
应该是:
Ok(Some(fs::read_to_string(entry.path())?))
这回答了你的问题吗?不,我不想忽略错误。这回答了你的问题吗?不。我不想忽略错误。Ahatranspose()
是丢失的链接!谢谢啊哈transpose()
是丢失的链接!谢谢同意,而且我甚至会将read\u entry
参数更改为entry:fs::DirEntry
,这样就可以在不使用额外闭包的情况下使用它,即.filter\u map(read\u entry)
但read\u dir()
返回结果
s..上的迭代器?同意,而且我甚至会将read\u entry
参数更改为entry:fs::DirEntry
,这样就可以在不使用额外闭包的情况下使用它,即.filter\u map(read\u entry)
但read\u dir()
返回结果
s..上的迭代器?