I've decided it's time to learn Rust and in order to keep myself motivated I'm going to keep a record of how the learning is going here.
A little about me; I'm a web developer and have been for around 5 years, though I'd dabbled for years. I have experience with Perl and PHP but my day to day is JavaScript/TypeScript be it through NodeJS or ReactJS. I want to learn Rust for no specific reason other than it's fun to learn new things.
My first port of call was to google learn rust
which lead me to "the book". The book is a first steps guide written by the rust community for newbies (or Rustlings as they're called) to gain a 'solid grasp of the language'.
Learning in public
I've chosen to document my Rust learning journey openly because I believe in the power of learning in public. By sharing my successes, challenges, and insights, I will reinforce my own understanding and hopefully provide a resource for others on a similar path.
I've seen the value in this approach first-hand. I invite feedback, corrections and contributions from readers. Whilst I recognize that learning in public isn't for everyone, I've personally found it immensely beneficial and hope to inspire others to consider it. So, let's dive into the lessons.
Lesson 1 'Getting started'
This lesson is broken down into 3 sections:
- Installation
- Hello, World!
- Hello, Cargo!
Installation
I was relieved to see installation listed, I was worried I would have to look up how to install Rust. I'm on a Windows machine but decided I'd rather do my Rust learning in Linux, so I'll be using Ubuntu through WSL.
The install command looked easy enough it uses curl to download something and then pipes that through sh, so we can assume the downloaded item is a bash script of some kind.
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
Believe it or not this is where I made my first mistake. I saw the Rust is installed now. Great!
message and moved on to the next lesson. Had I read on a little further I'd have seen that I needed to install the compiler separately.
Linux users should generally install GCC or Clang, according to their distribution’s documentation. For example, if you use Ubuntu, you can install the build-essential package.
This was easily remedied though and I was back on track in no time.
sudo apt install build-essential
Hello, World!
The next section is a staple of the dev community, the beloved "Hello, World!" example.
There a few little bits I learnt here, functions are declared with the fn
keyword, the entry point for any rust application is the main
function within the main.rs
file and the standard naming convention is to use underscores to separate words in function and filenames.
It was at this stage I discovered I didn't have a compiler installed, which I think is the real reason for simple sections like this, to make sure we're all set up correctly.
Hello, Cargo!
The previous section was very simple, this section is also very simple but introduces us to cargo which is Rust's package manager, as a JS dev my mind goes straight to NPM.
Cargo allows us to do a few cool things:
- name our packages.
- add package dependancies.
- run our program in one command.
- build our program with debug mode and release mode.
- check our program compiles without actually building it.
The example gets us to recreate our Hello, World!
example but in the cargo way. The code is so simplistic it hardly feels worth showing but here it is.
fn main() {
println!("Hello, world!");
}
Lesson 2 'Guessing Game'
The second lesson doesn't have any subsections, the goal of the lesson is to program a guessing game where the user enters a number and we compare it to a randomly selected number, the game continues until the user has guessed the exact number.
We're still not doing anything ground breaking but the progress from printing static text to dynamically taking user input and returning a result is nice all the same.
VSCode
It was at this point I decided that doing code changes in nano
was not a great idea and I needed to open the project in VSCode. I added a few extensions to, hopefully, make development a little easier. These were rust-analyzer, crates and Even Better TOML. You can use any editor you like, I'm just used to VSCode.
Making the game
Let's look at the game tutorial, it has us use cargo to make set up the project and very quickly introduces us to a few new concepts
- The
use
keyword. - Mutable variables.
- Error handling.
- Cargo doc.
The use
keyword
The use
keyword allows us to pull in code from other libraries, as a web developer, I want to compare this to import. By default Rust will have access to a set of items from the 'standard' library, this is called the prelude, but if you want access to anything else you'll have to use use
.
In the example they give we do use std::io;
which allows us to access the io
namespace, this does feel a little weird though as we already had access to std
meaning std::io
is also accessible.
Mutable variables
In JavaScript land we have the concept of immutable and mutable variables, these are const
and let
where const
is immutable and let
isn't. Rust is a little different in that all variables are immutable unless specified otherwise, the variable keyword also is always let
, or at least it is as far as I can tell so far.
let mut var1 = String::new(); // mutable
let mut var2 = String::from("Test String"); // mutable
let var3 = 6; // immutable
The book let's us know here that it will be returning to mutability in lesson 3.
Error handling
We're introduced to two types of error handling .expect
which doesn't attempt any sort of recovery but helpfully posts a message as the application crashes and match
.
Match
takes the Result
from a function and then allows you to call a function based on the Result
. In the example we're given parse
and told it will either be Ok
or Err
, in the match
we are able to define a function to be called on either of these cases. I assume that when we start dealing with more diverse functions match will be able to handle all Result
types.
Cargo doc
This is my favourite part of Rust so far, I know it shouldn't be that exciting but I think it is. When you run the command cargo doc
Cargo will scan through all the code you're using a generate help pages explaining functions and how to use them.
There isn't much explanation of this yet but I'm hoping these docs are generated from comments in the code, even if this isn't that case code bases that can self document is just so interesting to me.
Wandering off the beaten track
At this point I was done with the first two lessons and decided to make a couple of changes to the guessing game. I extracted the game loop into its own function and I added an error message for failed parsing.
One thing I didn't like was the magic
of this line.
let guess: u32 = match guess.trim().parse()
I didn't like that it felt like parse just magically knew what type it was aiming for. So I read the tooltip for parse in VSCode and it taught be about the turbofish
syntax. I don't know if people don't like this syntax or if the writers of the book decided it was too complex for a beginner but to my eye is just made so much more sense. We tell parse what type we'd like and our let
infers type from that rather than the other way around.
let guess = match guess.trim().parse::<u32>()
Here is the modified code.
Signing off
Thank you for coming on this journey with me. I plan to continue this series and cover the entire book. If you'd like to follow along, you can press the 'follow' button to be notified of new posts.
As I said earlier feel free to leave any feedback and if you're learning in public too please leave a link to your series in the comments so I can check it out.
Thanks so much for reading. If you'd like to connect with me outside of Dev here are my twitter and linkedin come say hi 😊.
Top comments (10)
I've only done the next lesson after these and have already discovered how wrong I was about this 😅
Awesome! You'd be amazed by the power of traits. Be careful about noisy match statements in error handling though. Try using impl for error types!
For example,
impl From<Error> for MyOwnError {
fn from(err: Error) -> Self {
MyOwnError { message: "oh no! }
}
}
With that, whenever the Error type is returned and we say that the return type of a function when it errors is MyOwnError, the from function will be called.
Good luck!
I started with Rust by reading rust by example, from their website, but eventually bought a book - it worth the investment.
I am also adding tips that I found interesting as I rewrite my blog system. It was initially in D, but as a learning experience, I ported to Rust using ntex to process web requests - Texted2
It's being a great experience. So far, if it compiles, it runs :)
I also started learning rust, Andrew. I see some commonalities between C and Rust. But, it's my initial opinion.
Currently, I'm following the same book and alongside 30DaysOfRust series by inpyjama.
So far, it is very interesting for to learn and I'm directly coming from C language. Not familiar with anyother language.
Hi Andrew
I have also started learning Rust myself.
Looking for your next post and hope that we could help each other on this journey!
Rust is an amazing lang. I think it has a great future. Currently learning it too, made some simple apps already... Expecially was excited with WebAssembly: it can really speed up things.
That's great! I'm looking forward to trying some WASM stuff too.
How is the learning journey going?
It's going well so far, I aim to have the next post out on Monday 😊
Can I be part of your leaning track ?