25 Minutes of Rust (Episode 5)

In this episode I continue to build a Rust guessing game, using the book "The Rust Programming Language" as a guide.

I'm doing a series of 25 minute sessions where I try to get familiar with the Rust programming language. The blogposts in these series are the notes I took of the lessons learned along the way.

Warning to the reader: As always in this series, these are notes I take as I'm learning. They reflect my current understanding and may be incorrect!

Function Results

In the following lines of code something interesting is happening:

io::stdin().read_line(&mut guess)
    .expect("Failed to read line");

The read_line function doesn't return a number, bit it returns a Result:

io::Result<usize>

The io::Result is an "Enum". But it seems different from a C# "Enum".

In C# and Enum is more or less a way to give meaning to a numerical value: If a result of "1" indicates success, you can check for Result.Success instead of "1".

The Enum seems more complex in Rust, but the tutorial leaves out quite some details about it at this point.

Most that is said is that the io::Result enum can have two values:

  • Ok
  • Err

It also has a function called expect which you are forced to call, otherwise you get a compiler warning.

When the result is Ok then expect will return the usize result value the read_line call produced.

If the result us Err, the expect function will halt the program and print the given input message to the output.

In the tutorial, at this moment, nothing is done with the resulting usize value.

Cargo Crates

In Rust, the package manager (like npm or NuGet) is called Cargo. The packages it installs are Crates.

For the guessing tutorial, we install a Crate, rand that can generate random numbers.

I add the crate, via Cargo.toml and add the following line to my code:

extern crate rand;

The following error appears:

[rustc] use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via Cargo.toml instead? (see issue #27812)

This error confused me for some time, it was not clear to me how I could make it use Cargo.toml instead.

After installing a crate, it turns out, you must reload the project in Visual Studio Code. See Issue #98 of rls-vscode.

Cargo Crate Versioning

According to the book, the crates use semantic versioning (semver). If you add rand = "0.3.14", this means to get any version "with an API compatible to version 0.3.14". In practice, this means it'll update to 0.3.15 if it becomes available but not to version 0.4.0, for example.

This struck me as strange, because semver specifies the second version number to be MINOR. Which you increment when you add functionality in a backwards-compatible manner.

One would think it should then be safe to upgrade to 0.4.0 too.

Update June 19th 2018: No less than Rust itself, or at least the twitter account @rustlang, informed me this behaviour is correct:
For versions where the MAJOR version is 0 (0.4.0) the MINOR version behaves like the MAJOR version. According to the semver spec.
If the package version would've been 1.3.0 I would've received 1.4.0 automatically. So Cargo behaves completely as it should!

Anyway, to upgrade, we must run cargo update.

Conclusion

The concept of Enums in Rust is different from the same concept in C#, from what I can see. I'm looking forward to learning how they are defined.

The VS-Code RLS extension seems to have an issue with new crates, it requires reloading the project. Otherwise it shows a difficult to understand error.

Automatic updating to new versions of crates only goes for PATCH version increments, and only when you explicitly want to. You can do this by running cargo update.