Io E0308使用读卡器中的for行从文件中读取行。行()

Io E0308使用读卡器中的for行从文件中读取行。行(),io,rust,Io,Rust,我是一名经验丰富的开发人员,目前正在自学生锈,我正在编写一个简单的程序来读取文件中的行。我已经前后阅读了Rust std:io、std:result和其他文档,这些代码主要是直接从文档中获取的。我不明白为什么下面的程序不能编译 use std::io; use std::fs::File; use std::io::BufReader; use std::io::prelude::*; fn main() { File::open("./data/test") .map

我是一名经验丰富的开发人员,目前正在自学生锈,我正在编写一个简单的程序来读取文件中的行。我已经前后阅读了Rust std:io、std:result和其他文档,这些代码主要是直接从文档中获取的。我不明白为什么下面的程序不能编译

use std::io;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;

fn main() {
    File::open("./data/test")
        .map_err(|err| err.to_string())
        .and_then( |mut dataFile| { 
             let mut reader = BufReader::new(dataFile);
             for line in reader.lines() {
                println!("{}",line.unwrap());

             };                           
        });        
}
运行cargo build时收到的编译错误为

我正在运行Rust 1.4.0。

您不应该使用and_,而应该使用map

正确代码:

File::open("./data/test")
    .map_err(|err| err.to_string())
    .map(|mut dataFile| { 
         let mut reader = BufReader::new(dataFile);
         for line in reader.lines() {
            println!("{}",line.unwrap());
         };
    }); 
您可以在两个函数签名中看到它:

fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E>
fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E>
这里的关键区别在于,操作op必须在and_then的案例中返回封装在结果中的内容,而不必在map的案例中封装。您的闭包不会返回任何东西,所以在Rust看来它实际上返回了,并且不能匹配结果。但是可以匹配U,这就是为什么第二个签名有效。

您不应该使用and\U,而应该使用map

正确代码:

File::open("./data/test")
    .map_err(|err| err.to_string())
    .map(|mut dataFile| { 
         let mut reader = BufReader::new(dataFile);
         for line in reader.lines() {
            println!("{}",line.unwrap());
         };
    }); 
您可以在两个函数签名中看到它:

fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E>
fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E>
这里的关键区别在于,操作op必须在and_then的案例中返回封装在结果中的内容,而不必在map的案例中封装。您的闭包不会返回任何东西,所以在Rust看来它实际上返回了,并且不能匹配结果。但是,它可以匹配U,这就是为什么第二个签名可以工作。

As,并用于转换带有闭包的结果。当您想要更改内部类型时使用map,然后当您想要链接第二个结果而不嵌套它们时使用_

但是,这两种方法都不适合您的案例,因为您没有转换价值。相反,您需要匹配或if-let语句。这些对副作用更合适

此外,Rust使用snake_案例标识符,不需要将任何变量标记为可变的。这些都是编译后您会看到的编译器警告

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn main() {
    let f = File::open("./data/test")
        .map_err(|err| err.to_string());

    if let Ok(data_file) = f {
        let reader = BufReader::new(data_file);
        for line in reader.lines() {
            println!("{}", line.unwrap());
        };                           
    }        
}
As、and用于转换带有闭包的结果。当您想要更改内部类型时使用map,然后当您想要链接第二个结果而不嵌套它们时使用_

但是,这两种方法都不适合您的案例,因为您没有转换价值。相反,您需要匹配或if-let语句。这些对副作用更合适

此外,Rust使用snake_案例标识符,不需要将任何变量标记为可变的。这些都是编译后您会看到的编译器警告

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn main() {
    let f = File::open("./data/test")
        .map_err(|err| err.to_string());

    if let Ok(data_file) = f {
        let reader = BufReader::new(data_file);
        for line in reader.lines() {
            println!("{}", line.unwrap());
        };                           
    }        
}

我将此标记为答案,就好像mdup的答案很有帮助一样。Shepmaster解释了最好的方法是什么,这非常有帮助。好的,刚刚了解了5分钟的限制,因此对上面的拼写表示歉意,现在无法更正。我要补充的是,我最初是基于第4.7节错误处理文档中的examle来编写这段代码的[.我现在明白了他们为什么要使用map,因为在那个例子中,他们实际上是在链接输出。我确实第一次尝试使用匹配,但我在脑海中看到了它们是如何工作的,这真的很有帮助。谢谢我将此标记为答案,好像mdup的答案很有帮助。Shepmaster解释了最好的方法是什么,而它非常有用pful.OK,刚刚发现了5分钟的限制,所以对上面的拼写表示歉意,现在无法更正。我要补充的是,我最初是根据第4.7节错误处理文档中的examle来编写代码的[.我现在明白了他们为什么要使用map,因为在那个例子中,他们实际上是在链接输出。我确实有过第一次尝试使用匹配项,但我在脑海中看到了它们是如何工作错误的,这真的很有帮助。谢谢