The property of being more “efficient” can only apply to differences between the two versions. This rust-by-example page is quite confusing in my opinion, the way it’s presented; it should more clear about what kind of difference was made to the code and should refrain from unnecessarily re-formatting and re-ordering the code.
The actual differences being made is that
- the argument is generalized to any
AsRef<Path>, which is a very minor efficiency benefit, and also a convenience benefit
- the return type becomes
Result, resulting in better error handling ability
The comment at the end of the page seems completely nonsensical.
This process is more efficient than creating a String in memory especially working with larger files.
This comment would make sense if the presented “Beginner friendly method” would use read_to_string and a lines iterator on the String; but the way the code examples stand now, there’s barely any difference.
This problem seems to have been noticed already as the same page in the nightly docs features a “naive” example that’s actually doing something significantly different – based on their comment, that’s also the version that @Michael-F-Bryan seems to be describing above.
Funnily enough, using the supposedly “inefficient” read_to_string makes it a lot easier to avoid the overhead of creating lots of small owned Strings, because the lines iterator on str/String creates borrowed &strs by default anyways, and only by wrapping it into a helper function and adding something like .map(String::from), it re-gains the overhead of creating many small Strings.
Also, these new nightly docs still contain severe issues, as they claim
We also update read_lines to return an iterator instead of allocating new String objects in memory for each line.
which is just plain wrong (or at least awfully misleading), as far as I can tell. It implies that the iterator would not be creating new String allocations for every line. While it’s true that creating a Vec holding all the Strings is avoided, that overhead was arguably negligible compared to all the allocations of the Strings themselves. While it’s true that the (shallow data of the) String “objects” is no longer placed on the heap, most people will understand “allocating new String objects” completely differently. Maybe it’s referring to the fact that the String allocations don't necessarily exist at the same time anymore, but as it’s written that’s not what this sentence conveys to me either.
I’ve raised an issue for these concerns.