克隆特性 BufRead 的行时类型不匹配
Type mismatch when cloning the lines of the trait BufRead
为了更好地使用 Rust,我决定实现一个简单的词法分析器来逐行分析一些文档。
因为我必须在特征 BufRead
的行上至少迭代两次,所以我正在克隆 BufRead
的行,但出现以下错误:
error[E0271]: type mismatch resolving `<std::io::Lines<T> as std::iter::Iterator>::Item == &_`
--> <anon>:18:23
|
18 | let lines = lines.cloned();
| ^^^^^^ expected enum `std::result::Result`, found reference
|
= note: expected type `std::result::Result<std::string::String, std::io::Error>`
= note: found type `&_
error[E0271]: type mismatch resolving `<std::io::Lines<T> as std::iter::Iterator>::Item == &_`
我明白错误是什么,但是基于 following code,我如何告诉编译器 Iterator
的 Item
应该是什么,以便它可以正确地转换类型?
use std::fmt::Write;
use std::io::{BufRead, BufReader, Lines, Read};
pub struct DocumentMetadata {
language: String,
// ...
}
pub fn analyze<T: BufRead>(document: T) -> Result<DocumentMetadata, ()> {
let lines = document.lines();
let language = guess_language(&lines);
// Do more lexical analysis based on document language
Ok(DocumentMetadata {
language: language,
// ...
})
}
fn guess_language<T: BufRead>(lines: &Lines<T>) -> String {
let lines = lines.cloned();
for line in lines {
let line = line.unwrap();
// Try to guess language
}
"en".to_string()
}
#[test]
fn it_guesses_document_language() {
let mut document = String::new();
writeln!(&mut document, "# language: en").unwrap();
let document = BufReader::new(document.as_str().as_bytes());
match analyze(document) {
Ok(metadata) => assert_eq!("en".to_string(), metadata.language),
Err(_) => panic!(),
}
}
出于单元测试的目的,我正在构建一个带有 String
的缓冲区,但在正常使用中我从 File
.
中读取它
查看 Iterator::cloned
定义:
fn cloned<'a, T>(self) -> Cloned<Self>
where Self: Iterator<Item=&'a T>,
T: 'a + Clone
以及 io::Lines
的 Iterator
的实施:
impl<B: BufRead> Iterator for Lines<B> {
type Item = Result<String>;
}
您不能使用 cloned
,因为迭代器项不是引用。否则你不能 "tell" 编译器;这不是类型的工作方式。
As I have to iterate at least two times over the lines of the trait BufRead
, I am cloning the lines of my BufRead
这真的没有意义。克隆 reader 的行不会保存任何内容。事实上,它可能只会让事情 变得更糟 。您将创建一次字符串,除了克隆它们之外不使用它们,然后在您再次迭代时第三次创建它们。
如果您希望避免重新创建所有字符串,collect
将所有字符串放入 Vec
或其他集合中,然后迭代多次:
pub fn analyze<T: BufRead>(document: T) -> Result<DocumentMetadata, ()> {
let lines: Result<Vec<_>, _> = document.lines().collect();
let lines = lines.unwrap();
let language = guess_language(&lines);
// Do more lexical analysis based on document language
Ok(DocumentMetadata {
language: language,
// ...
})
}
fn guess_language<'a, I>(lines: I) -> String
where I: IntoIterator<Item = &'a String>,
{
for line in lines {
// Try to guess language
}
"en".to_string()
}
为了更好地使用 Rust,我决定实现一个简单的词法分析器来逐行分析一些文档。
因为我必须在特征 BufRead
的行上至少迭代两次,所以我正在克隆 BufRead
的行,但出现以下错误:
error[E0271]: type mismatch resolving `<std::io::Lines<T> as std::iter::Iterator>::Item == &_`
--> <anon>:18:23
|
18 | let lines = lines.cloned();
| ^^^^^^ expected enum `std::result::Result`, found reference
|
= note: expected type `std::result::Result<std::string::String, std::io::Error>`
= note: found type `&_
error[E0271]: type mismatch resolving `<std::io::Lines<T> as std::iter::Iterator>::Item == &_`
我明白错误是什么,但是基于 following code,我如何告诉编译器 Iterator
的 Item
应该是什么,以便它可以正确地转换类型?
use std::fmt::Write;
use std::io::{BufRead, BufReader, Lines, Read};
pub struct DocumentMetadata {
language: String,
// ...
}
pub fn analyze<T: BufRead>(document: T) -> Result<DocumentMetadata, ()> {
let lines = document.lines();
let language = guess_language(&lines);
// Do more lexical analysis based on document language
Ok(DocumentMetadata {
language: language,
// ...
})
}
fn guess_language<T: BufRead>(lines: &Lines<T>) -> String {
let lines = lines.cloned();
for line in lines {
let line = line.unwrap();
// Try to guess language
}
"en".to_string()
}
#[test]
fn it_guesses_document_language() {
let mut document = String::new();
writeln!(&mut document, "# language: en").unwrap();
let document = BufReader::new(document.as_str().as_bytes());
match analyze(document) {
Ok(metadata) => assert_eq!("en".to_string(), metadata.language),
Err(_) => panic!(),
}
}
出于单元测试的目的,我正在构建一个带有 String
的缓冲区,但在正常使用中我从 File
.
查看 Iterator::cloned
定义:
fn cloned<'a, T>(self) -> Cloned<Self>
where Self: Iterator<Item=&'a T>,
T: 'a + Clone
以及 io::Lines
的 Iterator
的实施:
impl<B: BufRead> Iterator for Lines<B> {
type Item = Result<String>;
}
您不能使用 cloned
,因为迭代器项不是引用。否则你不能 "tell" 编译器;这不是类型的工作方式。
As I have to iterate at least two times over the lines of the trait
BufRead
, I am cloning the lines of myBufRead
这真的没有意义。克隆 reader 的行不会保存任何内容。事实上,它可能只会让事情 变得更糟 。您将创建一次字符串,除了克隆它们之外不使用它们,然后在您再次迭代时第三次创建它们。
如果您希望避免重新创建所有字符串,collect
将所有字符串放入 Vec
或其他集合中,然后迭代多次:
pub fn analyze<T: BufRead>(document: T) -> Result<DocumentMetadata, ()> {
let lines: Result<Vec<_>, _> = document.lines().collect();
let lines = lines.unwrap();
let language = guess_language(&lines);
// Do more lexical analysis based on document language
Ok(DocumentMetadata {
language: language,
// ...
})
}
fn guess_language<'a, I>(lines: I) -> String
where I: IntoIterator<Item = &'a String>,
{
for line in lines {
// Try to guess language
}
"en".to_string()
}