-
Notifications
You must be signed in to change notification settings - Fork 20
parse_line
method for Stdin
#207
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
Comments
Reading only a I think something more like rust-lang/rfcs#3196 (comment) would be the way forward here. With that, let c: char = std::io::inputln(); would still work, but it doesn't immediately throw people off the deep end if they want to read a number, since it could also accept let guess: i32 = std::io::inputln(); |
Tbh I think the guessing game in the book is quite a difficult example to start with. The book gets away with it because it assumes prior programming experience, but for someone without any prior programming experience, the guessing game is a little too much I think. At the very least, it requires the reader to take a lot of stuff for granted without fully understanding them. Even if it is "just" a char, that does enable quite some things. You could do TicTacToe, Hangman or even chess. Just because you can't do the guessing game doesn't make it not useful :) As for rust-lang/rfcs#3196, that looks interesting! However, there's multiple problems:
Some of that is already said in this comment rust-lang/rfcs#3196 (comment) With all that said, there's no reason you couldn't have both |
This assumes that one tries to teach bottom-up understanding from the start. |
Definitely - and some people learn best that way. Top-down explanations work for some, but it often involves a "leap of faith" from the learner to just accept what is being presented without understanding. In my opinion, top-down suffers from a feeling of being overwhelmed with concepts that you don't understand and losing overview of what you do understand. In general, people have very different ways of learning. I think it'd be best if we cater to more than just the "top-down" approach. It works for some, not for others. |
read_line_as_char
method for Stdin
parse_line
method for Stdin
After some discussion on Zulip, I agreed that the generic version that doesn't only work with This does make the proposal very similar to rust-lang/rfcs#3196, except it includes a parsing step. |
See also: |
I prefer the approach laid out here where parsing is done as part of the input. This also avoids allocating a string. And if you want a string, just parse into a string. Including the parsing does have the disadvantage that you muddle the io error and the parsing error into one call. But I suspect you'd probably handle these errors the same in many cases anyway (i.e. basically bubble them up to the user somehow and quit or ignore the error and fallback to some default). But we could also have both, I suppose. Having anything would be a big bonus. The current state of input in Rust using the standard library is frankly sad. This has unfortunately been left for a long time and I'm not sure what has even happened with the ACP process at this point. |
Proposal
Add a
fn parse_line<T: FromStr>(&self) -> io::Result<T>
method tostd::io::Stdin
to allow easier user input to be acquired without requiring deep knowledge of heap allocation,String
and such. This would significantly lower the barrier to entry for entirely new Rust programmers.It's also just a nice shortcut through
Stdin::read_line
+str::parse
Problem statement
Consider the task of teaching someone Rust as their first programming language. The leap from programs that take no user input to programs that do is very high at the moment. This is a problem because programs that do take user input are vastly more interesting for educational purposes.
Currently, in order to write a simple program that takes user input, you have to use
Stdin::read_line
. Unfortunately, using this method requires the user to understandString
, which in turn requires the user to understand heap allocation. The user also needs to understand mutable references, which preclude some level of familiarity with ownership. This is a big ask for someone being introduced to programming through Rust for the first time.It becomes an even bigger problem once the user input has been received. In order to transform the
String
into another type (say, au32
), one likely would want to callstr::parse
. In order to fully understand this method, one must know aboutFromStr
, which in turn means the user needs to also understand traits. This is a lot of knowledge that a user must know up-front before they can write any program that takes user input! This is a big problem educationally speaking.Motivation, use-cases
By introducing
parse_line
, we can severely lower the barrier to entry for programs that take user input by bypassing the need for anyString
in the midst. Receiving user input can be as simple as:Explaining the above program is significantly simpler than explaining a similar program using
read_line
andstr::parse
.For example, one could use this to teach a new Rust programmer to write a simple terminal-based TicTacToe game. Doing so currently is much harder as you have to use
read_line
.One could question if this motivation is sufficient for inclusion in the Standard Library. I personally think the Standard Library should also function as an "onboarding ramp" to a certain extent. It mostly does this through its documentation, but I think this kind of functionality could also help. Adding this functionality certainly doesn't hurt much - I find it very unlikely that it will be a maintenance burden or a future compatibility risk.
It's also worth mentioning that getting similar functionality as
parse_line
into the hands of an unexperienced Rust user is very, very difficult without including it in the Standard Library. Doing so would probably involve an external crate - however directing a new user towards such a crate requires them to learn about Cargo and general package management and then we get into a whole different problem.Aside from the above educational motivation, the API also serves an ergonomic improvement over the current workflow:
The current approach requires two errors to be handled rather than one - this is an improvement in cases where the error handling for the two possible errors (input error and parse error) are the same. This is often the case in small programs.
parse_line
also reduces the number of lines and makes input+parsing into a one-liner.I think including this API would fit well with the Supportive Rust goal as presented here.
Solution sketches
A straightforward implementation of
parse_line
in terms ofread_line
andstr::parse
could look like this:This solution does not properly handle panics in the
parse
method but barring panics, the behavior should be identical.A more efficient solution that handles panics could look like this:
This would actually make
parse_line
more efficient thanread_line
+parse
as it takes advantage of the buffering of stdin.Links and related work
See also discussion on Zulip
C++'s
cin
works in a similar generic fashion:What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
The text was updated successfully, but these errors were encountered: