Rust 如何返回';由接受&';多个自组织(当自组织在本地创建时)?

Rust 如何返回';由接受&';多个自组织(当自组织在本地创建时)?,rust,Rust,更新:文章标题已更新,答案已从问题中删除。简单的回答是你不能。请看我对这个问题的回答。 我正在关注一篇错误处理博客文章(github就是这样),我试图对代码进行一些修改,以便search函数返回一个迭代器,而不是Vec。这太难了,我被卡住了 我已经说到这一点: fn搜索, FnMut(结果) ->选项>, CliError>{ 让mut found=vec![]; 让输入:Box=match*文件路径{ None=>Box::new(io::stdin()), Some(ref file_pat

更新:文章标题已更新,答案已从问题中删除。简单的回答是你不能。请看我对这个问题的回答。

我正在关注一篇错误处理博客文章(github就是这样),我试图对代码进行一些修改,以便
search
函数返回一个
迭代器,而不是
Vec
。这太难了,我被卡住了

我已经说到这一点:

fn搜索,
FnMut(结果)
->选项>,
CliError>{
让mut found=vec![];
让输入:Box=match*文件路径{
None=>Box::new(io::stdin()),
Some(ref file_path)=>Box::new(try!(fs::file::open(file_path)),
};
让mut rdr=csv::Reader::from_Reader(输入);
让闭包=|行:结果|->选项{
让行=匹配行{
Ok(行)=>行,
Err(Err)=>返回一些(Err(From::From(Err)),
};
匹配行。人口{
无=>无,
一些(计数)=>如果row.city==城市{
一些(好的)(人口计数{
城市:罗,城市,
国家:row.country,
伯爵:伯爵,
}))
}否则{
没有一个
}
}
};
let found=rdr.decode::().filter\u映射(闭包);
如果!找到。全部(|行|匹配行{
好的()=>正确,
_=>错误,
}) {
错误(CliError::NotFound)
}否则{
Ok(找到了)
}
}
编译器出现以下错误:

src/main.rs:97:1: 133:2 error: the trait `core::marker::Sized` is not implemented for the type `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` [E0277]
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError>  {
src/main.rs:98     let mut found = vec![];
src/main.rs:99     let input: Box<io::Read> = match *file_path {
src/main.rs:100         None => Box::new(io::stdin()),
src/main.rs:101         Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102     };
                ...
src/main.rs:97:1: 133:2 note: `core::ops::FnMut(core::result::Result<Row, csv::Error>) -> core::option::Option<core::result::Result<PopulationCount, csv::Error>>` does not have a constant size known at compile-time
src/main.rs:97 fn search<'a, P: AsRef<Path>>(file_path: &Option<P>, city: &str) -> Result<FilterMap<csv::reader::DecodedRecords<'a, Box<Read>, Row>, FnMut(Result<Row, csv::Error>) -> Option<Result<PopulationCount, csv::Error>>>, CliError>  {
src/main.rs:98     let mut found = vec![];
src/main.rs:99     let input: Box<io::Read> = match *file_path {
src/main.rs:100         None => Box::new(io::stdin()),
src/main.rs:101         Some(ref file_path) => Box::new(try!(fs::File::open(file_path))),
src/main.rs:102     };
                ...
error: aborting due to previous error
src/main.rs:131:12: 131:17 error: mismatched types:
 expected `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, F>`,
 found    `core::iter::FilterMap<csv::reader::DecodedRecords<'_, Box<std::io::Read>, Row>, [closure src/main.rs:105:19: 122:6]>`
(expected type parameter,
found closure) [E0308]
src/main.rs:131         Ok(found)
这给了我一个错误:

src/main.rs:107:21: 107:24 error: `rdr` does not live long enough
src/main.rs:107     let mut found = rdr.decode::<Row>().filter_map(move |row| {
                                    ^~~
src/main.rs:100:117: 130:2 note: reference must be valid for the lifetime 'a as defined on the block at 100:116...
src/main.rs:100     -> Result<(Box<Iterator<Item=Result<PopulationCount, csv::Error>> + 'a>, csv::Reader<Box<io::Read>>), CliError> {
src/main.rs:101     let input: Box<io::Read> = match *file_path {
src/main.rs:102         None => box io::stdin(),
src/main.rs:103         Some(ref file_path) => box try!(fs::File::open(file_path)),
src/main.rs:104     };
src/main.rs:105     
                ...
src/main.rs:106:51: 130:2 note: ...but borrowed value is only valid for the block suffix following statement 1 at 106:50
src/main.rs:106     let mut rdr = csv::Reader::from_reader(input);
src/main.rs:107     let mut found = rdr.decode::<Row>().filter_map(move |row| {
src/main.rs:108         let row = match row {
src/main.rs:109             Ok(row) => row,
src/main.rs:110             Err(err) => return Some(Err(err)),
src/main.rs:111         };
                ...
error: aborting due to previous error
src/main.rs:107:21:107:24错误:`rdr`寿命不够长
src/main.rs:107让mut-found=rdr.decode::().filter_-map(move | row |{
^~~
src/main.rs:100:117:130:2注:引用必须在100:116块上定义的生命周期“a”内有效。。。

src/main.rs:100->Result返回迭代器是可能的,但它有一些限制

为了证明这是可能的,有两个示例,(A)使用显式迭代器类型,(B)使用装箱

使用std::iter::FilterMap;
fn为偶数(elt:i32)->选项{
如果elt%2==0{
一些(英语)
}else{None}
}
///(A)
国际热核实验堆(iter:I)
->过滤器映射选项>
{
iter.into_iter().filter_映射(是偶数)
}
///(B)
pub fn累计金额
其中I:into迭代器,
I::IntoIter:“a,
{
框::新(iter.into_iter().scan(0,| acc,x |{
*acc+=x;
一些(*acc)
}))
}
fn main(){
//输出为:
//0是偶数,10是偶数,
//  1, 3, 6, 10, 
即使是在晚上(vec![0,3,7,10]){
打印!(“{}是偶数,”,偶数);
}
println!(“”);
对于累积金额(1..5)中的cs{
打印!(“{},”,cs);
}
println!(“”);
}
您遇到了一个问题(a)--显式类型!未装箱闭包,我们从带有
|a,b,c |..
语法的正则lambda表达式中得到的闭包,具有唯一的匿名类型。函数需要显式返回类型,因此这在这里不起作用

返回闭包的一些解决方案:

  • 使用函数指针
    fn()
    ,如示例(a)所示。通常,您不需要闭包环境
  • 这是合理的,即使迭代器现在不支持调用它。这不是你的错
  • 框选迭代器
  • 返回自定义迭代器结构。需要一些样板文件
您可以在示例(B)中看到,我们必须非常小心使用生命周期。它表示返回值为
Box此答案基于irc.mozilla.org上的#rust提供的s+帮助

代码中不明显的一个问题,导致了上面显示的最后一个错误,与
csv::Reader::decode
的定义有关(参见其)。它需要
和一个mut self
,这个问题的解释包含在这里。这基本上会导致读卡器的生存期被限制在它调用的块上。解决这个问题的方法是将函数一分为二(因为我无法控制函数定义,正如前面的回答链接中所建议的那样)。我需要一个在
main
函数中有效的读卡器生存期,这样读卡器就可以被传递到
search
函数中。请参阅下面的代码(它肯定可以被进一步清理):

fn总体计数框行,
Err(Err)=>返回一些(Err(Err)),
};
匹配行。人口{
无=>无,
如果row.city==city=>{
一些(好的)(人口计数{
城市:罗,城市,
国家:row.country,
伯爵:伯爵,
}))
},
_=>没有,
}
}))
}
fn获取读取器(文件路径:&Option

) ->结果 { 让输入:Box=match*文件路径{ None=>Box::new(io::stdin()), Some(ref file_path)=>Box::new(try!(fs::file::open(file_path)), }; Ok(csv::Reader::from_Reader(输入)) } fn搜索 { 人口计数(读码器解码:(),城市) } fn main(){ 让args:args=Docopt::new(用法) 然后(| d | d.decode()) .unwrap_或_else(| err | err.exit()); let reader=get_reader(&args.arg_数据_路径); 让mut reader=匹配读取器{ Err(Err)=>致命!(“{}”,Err), Ok(读卡器)=>读卡器, }; let populations=search(&mut reader,&args.arg_city); 让mut-found=false; 针对流行人群{ 发现=真; 火柴流行音乐{ Err(Err)=>致命!(“致命!!{}”,Err), Ok(pop)=>println!(“{},{}:{}”,pop.city,pop.country,pop.count), } } 如果!(找到| | args)