E_n*_*ate 8 iterator type-inference rust
我最初的目标是获取一个单词列表,每行一个HashSet,并将它们放入a中,同时丢弃注释行并正确地引发I/O错误.给定文件"stopwords.txt":
a
# this is actually a comment
of
the
this
Run Code Online (Sandbox Code Playgroud)
我设法使代码编译如下:
fn stopword_set() -> io::Result<HashSet<String>> {
let words = Result::from_iter(
BufReader::new(File::open("stopwords.txt")?)
.lines()
.filter(|r| match r {
&Ok(ref l) => !l.starts_with('#'),
_ => true
}));
Ok(HashSet::from_iter(words))
}
fn main() {
let set = stopword_set().unwrap();
println!("{:?}", set);
assert_eq!(set.len(), 4);
}
Run Code Online (Sandbox Code Playgroud)
这是一个也在上面创建文件的游乐场.
我期望在程序结束时有一组4个字符串.令我惊讶的是,该函数实际上返回一个包含单个字符串的集合,其中所有单词都连接在一起:
{"aofthethis"}
thread 'main' panicked at 'assertion failed: `(left == right)` (left: `1`, right: `4`)'
Run Code Online (Sandbox Code Playgroud)
在文档中的一条建议的带领下FromIterator,我摆脱了所有的调用from_iter和使用collect(Playground),这确实解决了问题.
fn stopword_set() -> io::Result<HashSet<String>> {
BufReader::new(File::open("stopwords.txt")?)
.lines()
.filter(|r| match r {
&Ok(ref l) => !l.starts_with('#'),
_ => true
}).collect()
}
Run Code Online (Sandbox Code Playgroud)
为什么先前的调用from_iter导致意外的推断,同时collect()按预期工作?
更简单的复制:
use std::collections::HashSet;
use std::iter::FromIterator;
fn stopword_set() -> Result<HashSet<String>, u8> {
let input: Vec<Result<_, u8>> = vec![Ok("foo".to_string()), Ok("bar".to_string())];
let words = Result::from_iter(input.into_iter());
Ok(HashSet::from_iter(words))
}
fn main() {
let set = stopword_set().unwrap();
println!("{:?}", set);
assert_eq!(set.len(), 2);
}
Run Code Online (Sandbox Code Playgroud)
问题是,在这里,我们从迭代器中收集两次.类型words是Result<_, u8>.但是,Result 也实现了Iterator自己,所以当我们最后调用from_iter它时,编译器会发现Ok类型必须是String由方法签名引起的.向后工作,你可以String从迭代器构造一个Strings,这就是编译器选择的东西.
删除第二个from_iter将解决它:
fn stopword_set() -> Result<HashSet<String>, u8> {
let input: Vec<Result<_, u8>> = vec![Ok("foo".to_string()), Ok("bar".to_string())];
Result::from_iter(input.into_iter())
}
Run Code Online (Sandbox Code Playgroud)
或者你原来的:
fn stopword_set() -> io::Result<HashSet<String>> {
Result::from_iter(
BufReader::new(File::open("stopwords.txt")?)
.lines()
.filter(|r| match r {
&Ok(ref l) => !l.starts_with('#'),
_ => true
}))
}
Run Code Online (Sandbox Code Playgroud)
当然,我通常建议使用collect,因为我更喜欢链接:
fn stopword_set() -> io::Result<HashSet<String>> {
BufReader::new(File::open("stopwords.txt")?)
.lines()
.filter(|r| match r {
&Ok(ref l) => !l.starts_with('#'),
_ => true,
})
.collect()
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
90 次 |
| 最近记录: |