Skip to content

Replaced "non-efficient" implementation #1681

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

Closed
wants to merge 3 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions src/std_misc/file/read_lines.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
# `read_lines`

## Beginner friendly method

This method is NOT efficient. It's here for beginners
who can't understand the efficient method yet.

```rust,no_run
use std::fs::File;
use std::io::{ self, BufRead, BufReader };
use std::io::Read;

fn read_lines(filename: String) -> io::Lines<BufReader<File>> {
fn read_lines(filename: String) -> Vec<String> {
// Open the file in read-only mode.
let file = File::open(filename).unwrap();
// Read the file line by line, and return an iterator of the lines of the file.
return io::BufReader::new(file).lines();
let mut file = File::open(filename).unwrap();

// Read file contents into a String buffer.
let mut buffer = String::new();
file.read_to_string(&mut buffer).unwrap();

// Parse the buffer line by line, and collect into a `Vec<String>`
buffer.lines().map(|line| line.to_owned()).collect()
}

fn main() {
// Stores the iterator of lines of the file in lines variable.
// Stores a Vector of lines of the file in lines variable.
let lines = read_lines("./hosts".to_string());
// Iterate over the lines of the file, and in this case print them.
for line in lines {
println!("{}", line.unwrap());
println!("{}", line);
}
}
```

Running this program simply prints the lines individually.

```shell
$ echo -e "127.0.0.1\n192.168.0.1\n" > hosts
$ rustc read_lines.rs && ./read_lines
Expand All @@ -34,10 +41,11 @@ $ rustc read_lines.rs && ./read_lines
```

## Efficient method

The method `lines()` returns an iterator over the lines
of a file.

`File::open` expects a generic, `AsRef<Path>`. That's what
`File::open` expects a generic, `AsRef<Path>`. That's what
`read_lines()` expects as input.

```rust,no_run
Expand Down Expand Up @@ -67,6 +75,7 @@ where P: AsRef<Path>, {
```

Running this program simply prints the lines individually.

```shell
$ echo -e "127.0.0.1\n192.168.0.1\n" > hosts
$ rustc read_lines.rs && ./read_lines
Expand All @@ -75,4 +84,4 @@ $ rustc read_lines.rs && ./read_lines
```

This process is more efficient than creating a `String` in memory
especially working with larger files.
especially working with larger files.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider

This process is more efficient than creating a `String` in memory,
especially when working with larger files.

Copy link
Author

@arthurmilliken arthurmilliken Feb 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right. Also consider this comment at the top of the file:

This method is NOT efficient. It's here for beginners
who can't understand the efficient method yet.

Shouldn't the implementation given actually be an "inefficient" in-memory approach, given this comment at the top of the file?

As it currently stands, both the "inefficient" and "efficient' approaches use the exact same implementation, calling io::BufReader::new(file).lines() to parse the file. Why go through all the trouble of warning the user that the first implementation is "NOT efficient", when it uses the exact same approach as the "efficient" solution?

Shouldn't the two approaches actually be different from each other?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, I was merely commenting on the punctuation and the when in this sentence.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm 100% in sync with the change you propose here, although you'll have to duke it out with #1679

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, understood, thanks for the clarification!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed the proposed update, but looks like #1679 goes through a little more trouble to clean up the prose 😄

Copy link

@theredpea theredpea Mar 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate this pull request #1681, thanks @arthurmilliken , but I guess I prefer #1679 because its beginner friendly method(s) are more accessible to my beginner brain! (and more consistent with the beginner-friendly methods proposed in #1480)
#1679 's beginner friendly methods:

  • avoids &mut
  • avoids closure syntax | line | line.to_owned()
  • uses line breaks to help readability/fluency

Thanks again for everyone's help, it's great to reinforce my learning Rust :)