Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Explain why/when .lines() returns an error #37744

Closed
anholt opened this issue Nov 13, 2016 · 3 comments
Closed

docs: Explain why/when .lines() returns an error #37744

anholt opened this issue Nov 13, 2016 · 3 comments
Labels
E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.

Comments

@anholt
Copy link

anholt commented Nov 13, 2016

context: I'm doing the newbie Rust thing of writing some program that reads lines of a file. From stackoverflow I find myself at BufReader.lines() and then BufRead.lines() docs.

What I'm finding confusing in the docs is that lines() returns a Result, but the example in the docs blindly unwrap()s that result, and so does every caller of lines() I find in demo code. It would be nice if BufRead (or, if it's more appropriate there, then maybe in BufReader's impl) would explain under what circumstances you'd get an error instead of Ok when reading a file, so I know if unwrap() is appropriate to use or not.

@bluss bluss added A-docs E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. labels Nov 13, 2016
@bluss
Copy link
Member

bluss commented Nov 13, 2016

As a general rule for IO: it's interacting with an environment that's outside of the program's control, so errors can never really be ruled out. When BufReader’s operations return an error depends on which Read implementation it is wrapping.

A good reason to not use .unwrap() is composability. You're writing a larger program, and you don't want unwraps or error handling spread throughout the smaller helper functions. Instead each of them bubble up errors so that you can handle errors at a higher level (and in fewer places). The macro try!() and equivalently the operator ? are made for that.

Below there's a new example. The both read all functions do the same thing. Using collect() felt a bit cryptic for an example, but that's what you would use for that particular task (just gathering the results from an iterator). In general, lots of functions will be using ? (or equivalently try!()) instead, and the second read all function shows that.

use std::io;
use std::io::prelude::*;

fn main() {
    let stdin = io::stdin();
    let lines = match read_all_lines(stdin.lock()) {
        Err(err) => {
            println!("Failed to read input: {}", err);
            ::std::process::exit(1);
        }
        Ok(result) => result,
    };

    //  continue the program with lines: Vec<String>
}

fn read_all_lines<R: BufRead>(reader: R) -> Result<Vec<String>, io::Error> {
    // magic: .collect() can transform an iterator of Result<T, E> into a Result<Vec<T>, E>!
    reader.lines().collect()
}

fn read_all_lines_2<R: BufRead>(reader: R) -> Result<Vec<String>, io::Error> {
    let mut lines = Vec::new();
    for line_result in reader.lines() {
        // magic? return with an error if there is an error,
        // otherwise push the String to the vector.
        lines.push(line_result?);
    }
    Ok(lines)
}

@anholt
Copy link
Author

anholt commented Nov 15, 2016

Yeah, that seems a bit overcomplicated for the example in that section, and I like that the current example keeps the lines as an iterator instead of collecting.

What I'm looking for is a note like "Note that stdin.lines() may return an ErrorKind::Interrupted when ^C is hit, which would panic on the unwrap()" or something. What got me here was trying to figure out what errors could happen when reading from a std::fs::File wrapped in a BufReader, or whether the unwrap() I had seen in every single example was actually safe.

@bluss
Copy link
Member

bluss commented Nov 15, 2016

Good request. The docs should indicate what kind of reading is done and if it would return the Interrupted error.

steveklabnik added a commit to steveklabnik/rust that referenced this issue Dec 24, 2016
Docs: Explain why/when `.lines()` returns an error

Fix rust-lang#37744.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
Projects
None yet
Development

No branches or pull requests

2 participants