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