Rust n00b question about Result etc,


#1

As I became interested in Rust, I started reading the online book.
This little piece of code has so much in it, that I can’t oversee it (yet).

io::stdin().read_line(&mut guess)
        .ok()
        .expect("Failed to read line");
  1. the first line I do understand
  2. the second line:
    - my first thought is that “ok” is a weird name for what it seems to do;
    it is more a kind of “error relay” isn’t it?
    - found it hard to find the ok method in the docs;
    generally how can I work out where definitions are?
    it seems to be related to Result and also io::Result
  3. the third line:
    • “expect” seems odd as a name as well!
      what is seems to do is display my own made up error, instead of a standard Rust exception;

Thinking about is I would name the “ok” method:
checkerror
and “expect”:
showerror
or something like that.
Does that make sense?

Also, why not have one method instead of the two? “ok” could have been named “iferror” and have your own error message as an argument.

Probably I don’t (yet) understand the philosophy of Rust and hence struggle with it for now!

TIA, Arie


#2

If you look at io::stdin() it returns the Stdin object. The read_line() method returns a io::Result which is an alias(?) for Result.

Result is a fairly common return value from functions. It lets you return an object on success and another object on error. Often my Error objects are just a string saying what went wrong. The ok() method returns the “succes” object however the result might have been an error, so it actually returns an Option which is another common return value. It lets you return an object on success or nothing on error.

The Option enum has the expect method which extracts the object from the Option if there was one, and if not panics (aborts execution) with the specified message. Personally I’ve never used the expect() method.

Normally for this line I would write something like:

if let Err(msg) = io::stdin().read_line(&mut guess) {
    panic!("Failed to read line: {}", msg);
}

This code does the same basic thing, if read_line() returns an Err object, then abort execution and log the reason. If you want the success object (in this case the number of characters read you can do:

match io::stdin().read_line(&mut guess) {
    Ok(count) => println!("Read {} characters.", count}),
    Err(msg) => panic!("Error reading stdin: {}", msg)
}

Which allows you access to the success object “count” on success and the error object “msg” on error.


#3

You don’t need .ok() here, io::stdin().read_line(&mut guess).expect("foo") works.

ok() is for converting to an Option, since Options have their own set of useful related APIs and work well with iterators.


#4

Both repliers many thanks!!


#5

I think at the time I wrote this, Result didn’t have expect on it. We should change the tutorial to remove the ok.


#6

Hi Steve,
yes, that makes it much clearer for beginners!
Thx, Arie


#7

Would you mind opening a bug so we don’t forget? Thanks!