Teaching Rust in 5 days

Tags: #rust

Reading time: ~13min


I gave a 5-day Rust course at my university and want to share my experience teaching Rust.

In this blog post, I want to answer the following questions:

Landscape mode recommended on mobile devices

About the course

The course I gave was a vacation course that students can sign up for. They don't get any credit points for it and they don't have to attend. It is just an opportunity to learn new skills that can help at the university. Nevertheless, about 12 students (in average over all 5 days) attended it and the feedback was positive!

We met everyday from 10 to 16 o'clock and had a lunch break from 12:45 to 13:30. This allowed two "sessions" with about two and a half hours each. The plan was that every day has the following structure:

This allows students that finish the exercises early to get a longer lunch break or go home earlier instead of getting bored waiting for the next content. It was also a wish of students from my previous courses to practice presented content as soon as possible instead of having exercises only at the end of the day.

That was the plan, but it didn't work everyday. If you want to try this format, you should be prepared to be flexible. On two days, I had to give students more time for the exercises after the break because many were not done yet. On the last day, we didn't have a lot of time left, therefore I had to present content the whole morning and at the beginning of the afternoon session. But I think that I can plan the sessions better next time after having a feeling of how long the topics and exercises take.

Note

You can find the course under this link:

comprehensive-rust.mo8it.com

But I would not recommend you using it to learn Rust on your own. It is designed for interactive teaching. For learning Rust on your own, I would rather recommend reading the official Rust book and doing Rustlings.

Requirements

The course was advertised with the requirement of basic programming skills (some experience in Python should be enough). I made this requirement more concrete with the following list of concepts that students have to know:

Although each additional requirement can save you time because you can just build on known concepts, each additional requirement can eliminate a part of your potential audience. Know your audience before choosing your course requirements.

My audience was students with computer science or physics background that attended at least their first programming lecture (currently in Python at my university). Therefore, I kept my list rather short.

That being said, you could save a lot of time if you require the following additional concepts:

Content

I like to write my courses myself, but I didn't want to reinvent the wheel since I found a very good Rust course that was compatible with the format of my course: Comprehensive Rust

Comprehensive Rust is a course created by the Android team at Google. It has three days that cover what they call "Rust fundamentals". In addition, it has:

For me, I was only interested in the three days about the fundamentals and in the day about concurrency since I advertised Rust as a language that empowers you to write correct parallel code.

I planned to use the remaining fifth day to cover aspects that we didn't have time for and to present some interesting use cases of Rust like building a web backend.

But it turned out that we needed 4 days for the fundamentals instead of 3. That was fine, I focused on quality instead of quantity. It is very important to give the basics their proper time. If the fundamentals are solid, students can build on them later on their own.

I had to shorten the content about concurrency from the original course to be able to fit it into the last day and still be able to present at least one use case.

After scratching the surface of multithreading and async in Rust, I presented building a web backend in Rust by following my blog post about Axum and Askama. The goal of that presentation was to show students how they are able to dive into specific topics/crates in Rust after learning the basics. Of course, you need the required knowledge about that specific topic. For web backends for example, you have to learn about GET and POST requests, routers, handlers etc. You also have to learn the API of the required crates. But Rust itself will not be a hurdle after learning its basics.

I didn't use Comprehensive Rust directly. Instead, I forked it and made mainly the following modifications:

The last point is very important. I really like the course that the Android team developed, but I wasn't convinced of the pedagogical value of its exercises (subjective opinion). I think that they are hard for a person that just started learning Rust. Sure, there are solutions which students could look at when they are stuck, but I also don't like the idea of providing solutions while students are working on the exercises. In addition, the exercises don't cover a lot of the presented content on that day because of them being 1-2 huge exercises for each session instead of many small ones.

So what replacement did I choose for the exercises?

Exercises

Rust already has a very good collection of exercises: Rustlings

Why reinvent the wheel? In my opinion, it is the best interactive learning resource for Rust. If you are looking for Rust exercises for beginners, just use Rustlings 😍

I forked Rustlings and made mainly the following modifications:

collective-score is a tool that I created in Rust for my courses this semester (not documented yet). It has three components: server, client and dashboard TUI. Here is how it works:

A screenshot of the dashboard TUI of collective-score

The mix of Rustlings and collective-score was a gamification that was very positively received! It was also a good way to monitor student's progress without watching over their shoulders.

I have many ideas to improve the dashboard TUI for the next time. It has a huge potential, especially to get feedback about which exercises were trivial and which ones were tricky and took many attempts.

Outcome

After 5 days, students were familiar with Rust's basics. We covered many aspects, from ownership and borrowing to multithreading and async. Students were surprised that we were able to cover all that content in 5 days!

We were not able to finish all 90 exercises, but the majority of students finished about 2/3 of them. I should have allocated more time for the exercises. This is something that can be planned better next time. But removing some of the exercises might be necessary.

Some students wrote in their feedback that they wanted some tasks where they don't only fix compiler errors and fill the gaps of existing code. They wanted tasks where they start a small project from scratch and write their own code. This is something that Rustlings don't provide. Therefore, I have to think about a small project for the next time that connects many of the learned concepts. I should allocate at least one hour for it on the last day. But again, to be able to achieve that, I have to reduce the number of Rustlings exercises.

Only 6 students filled out the anonymous feedback form πŸ₯² But from those that did it, the course got an overall rating of 4.3 stars out of 5 ⭐️ For the first time giving this course, I am more than happy with the outcome ☺️ But there is always room for improvement!

Topics to focus on

From my experience, people coming from other languages require more focus on the following topics because they are either completely new or not very familiar to them:

It is helpful to make a connection to similar concepts in the languages that the audience is familiar with.

For example, when you talk about iterators, you could compare them to list comprehension in Python.

When you talk about ownership and borrowing, explain what can go wrong when you have a mutable and an immutable reference at the same time! Of course, this (with the Send and Sync traits) makes data races impossible in Rust. But give an easier example, especially for people not familiar with concurrency. Show this tiny, but powerful example of iterator invalidation in Python:

l = [1, 2, 3]

for item in l:
    print(item)
    l.append(item)

The example above is an endless loop!

Or even worse, an unexpected behavior:

l = [1, 1, 2, 3]
for item in l:
    if item == 1:
        l.remove(item)

l == [1, 2, 3]

The example above is from Stack Overflow and shows that you get an unexpected result (there is still a 1 in the output list). The person mentioning this example says:

"The general rule is that you probably shouldn't do anything that would add or remove items while an iterator is doing it's thing"

I have good news for you: Rust would not allow such behavior!

When explaining traits, show an example that compares them to the usage of inheritance in object-oriented languages. Show them the MurderRobotDog problem (video) and implement the solution with traits in Rust. I found this example so good that I want to write a future blog post about it πŸ”ͺπŸ€–πŸ•οΈ

The rug analogy

I used an analogy to explain ownership and borrowing in Rust and students found it helpful.

The analogy is having a rug (value) and persons (immutable references) standing on it. If some person wants to modify the rug, this person (mutable reference) has to take it away for a while (to wash it for example). But Rust doesn't allow pulling the rug under the feet of others 🚨

Therefore, you can either have one mutable reference (a person modifying the rug while no one stands on it) OR one or more immutable references (multiple persons standing on the rug but no one can modify it).

Each rug has an owner that can use it either by standing on it or by modifying it, but the same rule above applies to him as any other person.

A lifetime tells you that a person will stay on his rug for at least that amount of time.

A reference counter (Rc) is an owner of a rug that counts how many stand on his rug to remove it after the last person steps down.

Arc is a reference counter that has to watch multiple doors for persons coming in.

A Mutex is an owner of a rug that only allows one person at a time to stand on his rug or modify it. Everyone else has to wait on the side while the rug is being used. But don't let some person sleep on the rug while others are waiting 😴 (dead lock)

Every analogy is limited. This analogy is no exception! It can't explain everything, but it helps getting a first intuition.

Summary

I used to agree with the statement that Rust is complicated because some tend to say that.

But now, after giving the 5-day Rust course at my university, I believe that it is a problem of having more learning resources AND willing to go out of the comfort zone to learn completely new concepts like ownership and borrowing.

After the course, students are not Rust experts. But they will not panic on the first borrowing or lifetime compiler error they encounter.

If students without much experience (some of them had only one lecture about Python) can learn the basics in 5 days, then I think that developers should stop calling Rust complicated.

I am not saying that Rust is easy. I could teach Python to the same students in about 2-3 days instead of 5. I know that because I also teach Python and Julia at my university. They are easier for sure, but: Is it all about things being easy?

Rust is neither easy nor complicated, it is a language that requires you to learn new concepts and read a book or take a course before being able to start hacking.

Rust already has excellent resources for learning on your own. We have the official Rust book (available for free) and Rustlings as leading examples. But we need more resources and initiatives in organizations that teach programming (like universities).

If you are in such an organization, bring Rust up!


Appendix

Other teaching resources

Rust 101 is an awesome university course! It might even be a better fit for you if you are trying to teach Rust at a university.

But I really like the approach of Comprehensive Rust. Using mdBook allows you to run your Rust code using the Rust playground in the background. You can even modify Rust code in the same "slide" and run it again (try it here). I really love this interactivity which can't be achieved in "pure" slides.

You might not want that amount of interactivity and prefer "real" slides with animations. In that case, check out Rust 101!


Credits

I want to thank my lovely local Rust group for their feedback and support while working on the course πŸ₯°

You can suggest improvements on the website's repository

Content license: CC BY-NC-SA 4.0