[Rust Syllabus] Which Exercises/PRs cover only concepts from chapter 3?

@isDineshHere (and everyone else) I’d like us not to give feedback on those PRs yet. We will get to that next week, and get them all merged in, but I want to take one step at a time, so everyone can learn about the feedback we want on each PR, rather than lots of people giving potentially conflicting (or incorrect) advice. :slight_smile:

(If we can all learn how to make great Concept Exercise PRs we’ll be able to increase the speed we can add new exercises and all work together to help other tracks etc. But there’s an alignment and knowledge-sharing step that needs to happen to get there. I want us to all have a very clear list of what Concept Exercises should be achieving to get them over the line. But I promise we’ll get to that soon, and get those PRs merged! :))

From my understanding this is how the 5 sub sections on Chapter 3 of the book are currently covered by open PRs and existing concept exercises.

3.1 Variables & Mutability

  • cars-assemble; does a bit of explainer of assignments in introduction.md as well as how to define a mutable variable. I don’t believe its enough to cover the section from the book


  • variable scope & shadowing
  • constants

3.2 Data Types

  • cars-assemble; covers: integers
  • annalyns-infiltration; covers: booleans
  • phone-number-analysis; covers: tuples
  • bird-watcher; covers: arrays
  • log-levels; covers: strings
  • interest-is-interesting: covers: floating-point-numbers


  • none

3.3 Functions

  • lucians-luscious-lasagna (solid candidate for functions & comments, might need some touch ups in docs)


  • none


  • none on their own


  • comments

3.5 Control Flow

  • cars-assemble; covers: if-statements
  • bird-watcher; covers: for-loops
  • interest-is-interesting; covers: while-loops



  • high-school-sweethearts; covers: string-formating
    String formatting is used in the book but not explicitly explained in Chapter 3

Out of Scope

  • logs-logs-logs; covers: enums
  • short-fibonacci; covers: vectors
  • semi-structured-logs; covers: enums
  • elons-toys; covers: structs
  • tim-from-marketing; covers: option
  • rpn-calculator; covers: vectors & stacks; requires: enums, match, option, slices
  • role-playing-game; covers: enum, option; requires: match, structs
  • resistor-color; covers: external crates, cargo, iterators, enums
  • magazine-cutout; covers: entry-api, hash-maps; requires: slices, iterators
  • low-power-embedded-game; covers: tuples, tuple-structs; requires: structs
  • health-statistics; covers: structs
  • csv-builder; covers: mutability & ownership
1 Like

@iHiD Here is my answer to your question. I mostly agree with Carl, but am more conservative: fewer PRs made it. Reasoning about the deviations at the bottom. The green ones are definitely covered by Chapter 3.


  • I disqualified #1669 High School Sweethearts because it seems the Book (at all) does not cover formatting strings to the extent that is required by the exercise.
  • I disqualified #1673 Log Levels because it deals with strings, whose Rust-peculiarity (subject of Chapter 4) is part of the exercise.
  • #1676 Phone Number Analysis deals only with String specific methods, which might be fine: a normal documentation search problem.

Apologies for the late reply, I have to fix my email notifications from the forum.

I think my list pretty much matches @MatthijsBlom and @isDineshHere . I would include Phone Number Analysis, because it states to deal with tuples, which are covered by chapter 3. I think @isDineshHere did not mention the existing assembly-line, which also fits the criteria (although the examplar uses match, which would not be appropriate at that point).

Side notes:

  • The log-levels PR is confusing to me, because the task seems to be exactly the same as the existing (non-concept) exercise semi-structured-logs.

  • The existing exercise low-power-embedded-game wants to teach tuples (part of chapter 3), but has structs as prerequisite. So that exercise probably won’t fit in the plan of modelling the syllabus after the Rust book.

Including the existing exercises and excluding everything that didn’t make the cut, I’m trying to answer this question as concisely as possible:

Out of the existing exercises (those Dinesh posted and those in the track already, which ones cover topics in Chapter 3 of the book).

Open PRs relevant to the Rust book chapter 3:

Existing exercises relevant to the Rust book chapter 3:

  • assembly-line
  • lucians-luscious-lasagna
1 Like

OK, thank you all.

So let’s get these ones into a good shape. Firstly, I want to start with a very clear pathway:

  • Every exercise has an examplar.rs. This should be the minimum to solve the exercise using the concepts learnt so far. It doesn’t have to be idiomatic. It can contain suboptimal practices. It’s the next step someone takes on their learning journey.
  • By comparing the stub (lib.rs) to the exemplar, we can work out what the introduction needs to teach. The introduction should only contain info about things used in the Exemplar that are not in the stub - ie the code someone writes. Other things can be touched on very loosely. Two examples from Lasagna:
    • We use +, - and * but we can also mention the existence of /. But we shouldn’t dwell on it.
    • We call functions, but we don’t create them. So we don’t need to explain pub or go into any detail about defining functions. But we should say “Rust has functions that are defined by use the keyword fn followed by the name. (You’ll also see visibility modifiers and param/return types, but don’t worry about those for now). You call functions by using the name and passing any arguments in parenthesis.”
  • For extra information that isn’t used in the Exemplar, but is topical, this should go in the after.md (which can be thought of as the introduction.md + extra info). Think of this after.md as more evergreen information on the concept.

So I’m going to go through and make notes on each one. I’m only looking at the exemplar and stub.

Lucians Luscious Lasagna (Basics)

I need to be taught:

  • Calling functions
  • -, +, *
  • Implicit returns

We also use this to cover any other basic information. However, looking at the current introduction there’s loads of unnecessary information in there. For example, we need nothing about let at this stage as it’s not used in the exercise, so let’s pull that out and use it in a different exercise later.


I need to be taught:

  • !
  • ||, &&
  • Explicit returns
  • That “bool” means “boolean” with a link to info on booleans.


  • Why are we using explicit returns here but implicit returns in lasagna. Let’s standardise


I need to be taught:

  • let
  • what round() is (a method?)
  • constants


I need to be taught:

  • floats
  • if
  • mut
  • while


  • Whatever info.1 is
  • split_at
  • Use of () with let
  • Whatever split_at(1).1 is


  • Why does this exercise have semicolons?


  1. Does everyone agree with that analysis? What have I missed?
  2. When we have consensus on that analysis, Dinesh, refine the introductions to achieve the points, and then tell people when you feel they’re ready for review. Then we can all weigh in.

Sound good?


There are some missing numeric operators which need to be thought also that concept teaches the basics of int and float.

  • Why are we using explicit returns here but implicit returns in lasagna. Let’s standardize

Different author, different style. We should be using implicit returns in any case (in my opinion).

  • Why does this exercise have semicolons?

Since you need to have semicolons in rust unless it is the last line

  • Whatever info.1 is

A form of indexing



  1. Does everyone agree with that analysis? What have I missed?

My thought would be to drop Implicit returns from the first exercise.
This may just be me but I find that teaching let in the basic concept is something that should be done.

I agree Annalyn’s Infiltration should not use return.

Yes, a ‘method’. Beware though: different languages mean different things by this term.

Rust doesn’t have classes or objects and such. As far as I know Rust’s ‘methods’ are just regular functions, except sorta-namespaced and with convenient syntax.

(input * 10.0).round()
// means the same thing as
f64::round(input * 10)

Cars Assemble also uses if, explicit return, and type casts.

Interest is Interesting uses the (void) add-assign operator +=.

This is struct field access. Tuples do not have named fields, but you can still get at them using this syntax. tuple.1 is the tuple’s second field, i.e. element.

That’s actually pattern matching (against a tuple).

A few other exercises have semicolons too.

Rust’s blocks ({ … }) are expressions. They consist of a series of ‘statements’ separated by semicolons, and their value is the value of the last statement. If the last statement is terminated with a semicolon (or, if you will, the last statement is empty) then the value of the block is () (the empty tuple / maximally boring value).

You could see the return keyword as syntactic sugar that makes it convenient to ‘return’ earlier.

I am quite sure that floats are defined in a struct and a struct if not object-oriented, so is it very close. And that struct has methods assigned to it. Methods and functions are different, but in this situation, they should be called methods since they correspond to an instance of a struct.

But of course there are functions as well, but when calling number.method so will it always be a method. Calling f64::round() is a function (I am pretty sure)

I just noticed I missed assembly-line. I’ll add that in later.

I’m having trouble understanding your meaning here.

The difference between Rust’s structs and ‘objects’ in other languages is that the latter ‘physically’ carry (in memory or through some sort of resolution at runtime) references to methods, whereas Rust’s structs don’t. Consequently, the semantic (might not be exactly the right word) differences between ‘functions’ and ‘methods’ that exist in those other languages do not exist in Rust.

Methods in Rust are just associated functions (book, reference) that are annotated with self as their first argument. (Rust Playground)

I suspect the dot syntax was chosen to be reminiscent of the object member access syntax from other languages. It is syntactic sugar for :: – see the reference.

Rust’s official linter, clippy, will complain if explicit returns are used where implicit ones are possible. I want to push our students to use clippy, so I’m strongly in favor of implicit returns.


I need to be taught (adding to Jeremy, @MatthijsBlom pointed these out already):

  • comparison operators ==, <, <= etc.
  • type casting with as

This is another one of those PRs where the task is almost identical as assembly-line. What’s up with that? Are we going to merge these two?

The rest of Jeremy’s analysis I agree with.

I mean that if you look in the source code, so will float be defined in a struct.

Rust is a bit weird about object-oriented programming in my personal opinion, meaning it doesn’t really act like other object-oriented languages.

As far as I understand so is the major difference between a function and a method, is that functions can only work with the provided data while methods can access all the data provided in the given instance. But as a grand rule, all “functions” defined inside a struct, enum or trait is a method and everything else is a function.

What source code? f64 is a compiler built-in primitive type. Why would it be defined inside a struct?

the major difference between a function and a method, is that functions can only work with the provided data while methods can access all the data provided in the given instance.

I don’t understand. In Rust, every function or method can only access what has been passed into it explicitly. The “method receiver” is just another argument and not treated in a special way.

But as a grand rule, all “functions” defined inside a struct, enum or trait is a method and everything else is a function.

Not really… While OOP languages often define methods right inside the class definition (literally inside the same curly braces), Rust doesn’t do that. Rust’s methods and associated functions are defined in impl blocks, which can be located anywhere. You can even add methods and associated functions to foreign types, ones from the standard library or third party crates, although you need to define a trait for that. Also, you can define “associated functions” in such blocks which do not take a method receiver (self). They are not called methods.

What source code? f64 is a compiler built-in primitive type. Why would it be defined inside a struct?

Other languages use a struct to define data types. But my bad, it was a pure guess, I had personally never seen the definition.

Don’t mean littarly inside.
In oop languages you can also deffine methods outside of a class:

module Methods
    def something

class Something
    include Methods

(You can also define a method outside of a module or class but then it becomes a class method (which is more or less a function but since in ruby everything is an object so is it a method) and not an instance method).

But also it makes sense that “functions” that don’t take self as a parameter is a function and I meant as a general rule, there are of course expectations.

I don’t understand. In Rust, every function or method can only access what has been passed into it explicitly. The “method receiver” is just another argument and not treated in a special way.

I mean that take for example python:

class Something:
    def __init__(self, abc):
        self.abc = abc
    def something(self, abc):
        self.abc = abc

(I know I deserve awards for my very good variable names)
We see here also self, since python can also only access what has been passed explicitly (it can although deal with global variables etc but that doesn’t matter here), but for example I wouldn’t be able to call the method “something” without having an instance of that class. I am pretty sure it is the same in rust when a method has self.

@Meatball Can you please, for clarity, provide us with a list of differences between functions and methods in Rust, each one together with a relevant reference to the Rust language reference?

I already provided everything I found, plus a code demo.

If/when you think the reference is wrong or incomplete, please argue why you think so, optionally with code samples. (I do not doubt that the ref is incomplete, and think it plausible that is wrong – just not in ways relevant here.)

This is true in the sense that to call a function, all arguments must be provided, including self. But that’s no different than regular functions. Methods in Rust can be passed around like regular function pointers, which I think you’re saying shouldn’t be possible(?). Methods in Rust really are just syntactic sugar for plain old functions.


In general I think what can be happening is that we are just missunderstanding each other.

A method takes an instance as a parameter aka have self in the begning, a function does not. A method has to be assigned along side a struct, enum or trait.

Rust book: ” Methods are similar to functions: we declare them with the fn keyword and a name, they can have parameters and a return value, and they contain some code that’s run when the method is called from somewhere else. Unlike functions, methods are defined within the context of a struct (or an enum or a trait object, which we cover in Chapter 6 and Chapter 17, respectively), and their first parameter is always self , which represents the instance of the struct the method is being called on”

@senekor Can you get this to compile? Rust Playground

@Meatball The book (note: not the reference) does say «unlike functions», but this is either sloppiness, or associated functions aren’t functions. Will you argue that associated functions aren’t functions? (Wouldn’t be the first time that naming has gone bad.)

I would call them functions since they dont take self.