Recap 1
The course so far
We've reached the end of the first part of the course and are about midway through the course.
In the second part, we'll be going through more advanced topics, like module structure, defining and using custom structs, enums, traits and generics, and take a deeper dive into memory management to get a better understanding of how Rust works under the hood.
But first, let's recap what we've learned so far by first looking at a small command line program that prints all of the contents in a directory and then creating a slightly more complex program as an exercise (in steps). This will also be the first time in the course where we'll be looking into recursion — recursively calling a function from within itself (if we ignore that one example where we used recursion to construct Roman numerals in part 5).
To be able to print all of the contents in a directory, we need to traverse through all of its possible subdirectories and their subdirectories and so on. This is a task where recursion is a natural solution. We can use a crawler function that goes through the entries in a given directory and calls itself recursively for each directory it encounters.
In this example, we'll have the crawler function collect the found entries in a vector.
We wrap the return value in an io::Result
to be able to propagate errors that may occur when reading the directory entries. Note also that we use &Path
as the parameter type instead of &str
— this will save some trouble when calling the function recursively with nested paths.
Then, we need to be able to list all the files and directories in a directory.
Finally, we get the nested directories by recursing into the crawler function whenever a directory is encountered in the listed entries. We also need to modify the function signature to take a mutable reference to a vector of found files so that we can update them in each function call instead of creating a new list of files for each subdirectory.
The recap exercise consists of implementing a command-line application that prints the contents of a directory in a tree-like fashion (a simplified version of the tree command).
The final application will be able to print the contents of a directory so that the printed output looks something like
.
Cargo.lock
Cargo.toml
src
main.rs
Summary of symbols
Symbol | Description |
---|---|
fn | Defines a function. Functions can have parameters and they may return back a value. If the return value is unspecified, the function returns by default a unit value () . |
r#""# | A raw string literal. Escape characters (e.g. \n ) are not processed but interpreted literally. May also contain unescaped double quotes " literally. |
let | Defines a new variable. If the variable name is already in scope, the old variable gets shadowed by the new one. |
mut | Qualifies a variable (let mut ) or a reference (&mut ) as mutable. |
:: | Serves as the path separator used to access items in a module hierarchy. For example the constant i32::MAX and the function String::from . |
as | Used to cast values between numeric types or other primitives. |
-> | Used to specify the return type of a function. |
use | Used to import items from other modules. |
& | When in front of a value, borrows it, i.e. takes a reference to it. |
&mut | When in front of a value, borrows it mutably, i.e. takes a mutable reference to it. |
* | When in front of a reference, dereferences it to the value behind the reference. |
if | Starts a conditional statement. |
if let | Combines if and let for a concise way to handle values that match a single pattern (e.g. if let Some(value) = foo { /* do stuff with value */ } ). |
match | Matches patterns. The first matching arm is evaluated and every possible value needs to be covered. |
panic! | Crashes and stops a running program. |
(a, b, ... ) | Defines or destructures a tuple |
[a, b, ... ] | Defines an array, or destructures an array or a slice |
break | Breaks out of a loop |
continue | Skips the rest of the current loop iteration and continues with the next iteration. |
loop | Loops until stopped by explicitly breaking the loop |
while | Loops as long as predicate evaluates to true |
for | Loops over an iterator by consuming the iterator values and binding them to variables. |
Hi! Please help us improve the course!
Please consider the following statements and questions regarding this part of the course. We use your answers for improving the course.
I can see how the assignments and materials fit in with what I am supposed to learn.
I find most of what I learned so far interesting.
I am certain that I can learn the taught skills and knowledge.
I find that I would benefit from having explicit deadlines.
I feel overwhelmed by the amount of work.
I try out the examples outlined in the materials.
I feel that the assignments are too difficult.
I feel that I've been systematic and organized in my studying.
How many hours (estimated with a precision of half an hour) did you spend reading the material and completing the assignments for this part? (use a dot as the decimal separator, e.g 8.5)
How would you improve the material or assignments?