Types 克隆trait BufRead的行时类型不匹配

Types 克隆trait BufRead的行时类型不匹配,types,rust,buffer,clone,lines,Types,Rust,Buffer,Clone,Lines,为了更好地使用Rust,我决定实现一个简单的lexer,逐行分析一些文档 由于我必须在traitBufRead的行上至少迭代两次,我正在克隆我的BufRead的行,但我得到以下错误: 错误[E0271]:类型不匹配解决`::Item==&_` -->,如何告诉编译器迭代器的项应该是什么,以便它能够正确地转换类型 use std::fmt::Write; use std::io::{BufRead, BufReader, Lines, Read}; pub struct DocumentMeta

为了更好地使用Rust,我决定实现一个简单的lexer,逐行分析一些文档

由于我必须在trait
BufRead
的行上至少迭代两次,我正在克隆我的
BufRead
的行,但我得到以下错误:

错误[E0271]:类型不匹配解决`::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!(),
    }
}
使用std::fmt::Write;
使用std::io::{BufRead,BufReader,line,Read};
发布结构文档元数据{
语言:字符串,
// ...
}
发布fn分析(文档:T)->结果{
让line=document.lines();
let language=猜测语言(&行);
//基于文档语言进行更多的词法分析
Ok(文档元数据){
语言:语言,
// ...
})
}
fn guess_语言(行:&行)->字符串{
让lines=lines.cloned();
排队{
让line=line.unwrap();
//猜语言
}
“en”。to_string()
}
#[测试]
fn it_猜测_文档_语言(){
让mut document=String::new();
writeln!(&mut文档,“#语言:en”).unwrap();
让document=BufReader::new(document.as_str().as_bytes());
匹配分析(文档){
Ok(metadata)=>assert_eq!(“en.to_string(),metadata.language),
呃()=>恐慌!(),
}
}
出于单元测试的目的,我正在使用
字符串构建一个缓冲区,但在正常使用中,我从
文件中读取它
查看定义:

fn cloned<'a, T>(self) -> Cloned<Self> 
    where Self: Iterator<Item=&'a T>, 
          T: 'a + Clone
您不能使用克隆的
,因为迭代器项不是引用。你不能以其他方式“告诉”编译器;这不是类型的工作方式

由于我必须在trait
BufRead
的行上至少迭代两次,因此我正在克隆我的
BufRead

这真的没有道理。克隆读者的台词不会拯救任何东西。事实上,这可能只会让事情变得更糟。您将创建一次字符串,除了克隆它们之外不使用它们,然后在再次迭代时第三次创建它们

如果希望避免重新创建所有字符串,
将所有字符串收集到一个
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()
}
pub fn analyze(文档:T)->结果{
让行:Result=document.lines().collect();
让线=线。展开();
let language=猜测语言(&行);
//基于文档语言进行更多的词法分析
Ok(文档元数据){
语言:语言,
// ...
})
}
fn猜一猜语言,
{
排队{
//猜语言
}
“en”。to_string()
}
查看定义:

fn cloned<'a, T>(self) -> Cloned<Self> 
    where Self: Iterator<Item=&'a T>, 
          T: 'a + Clone
您不能使用克隆的
,因为迭代器项不是引用。你不能以其他方式“告诉”编译器;这不是类型的工作方式

由于我必须在trait
BufRead
的行上至少迭代两次,因此我正在克隆我的
BufRead

这真的没有道理。克隆读者的台词不会拯救任何东西。事实上,这可能只会让事情变得更糟。您将创建一次字符串,除了克隆它们之外不使用它们,然后在再次迭代时第三次创建它们

如果希望避免重新创建所有字符串,
将所有字符串收集到一个
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()
}
pub fn analyze(文档:T)->结果{
让行:Result=document.lines().collect();
让线=线。展开();
let language=猜测语言(&行);
//基于文档语言进行更多的词法分析
Ok(文档元数据){
语言:语言,
// ...
})
}
fn猜一猜语言,
{
排队{
//猜语言
}
“en”。to_string()
}

这确实更有意义。我一直坚持克隆行的想法,因为
io::line
的大多数方法都使用迭代器,我认为
collect
不适合这种情况。谢谢事实上,这样做更有意义。我一直坚持克隆行的想法,因为
io::line
的大多数方法都使用迭代器,我认为
collect
不适合这种情况。谢谢