The Rust Programming Language
Table of Contents
IntroductionRichard Feldman introduces the course by discussing what Rust is made for, various companies that use Rust, and the benefits and drawbacks of using Rust as a programming language. An overview of what will be covered in this course and a student's question regarding what makes a slow compiler is also provided in this segment.
StringsRichard discusses string interpolation in Rust including how to print and return string variables to the terminal using println, format, and panic. The panic command is only at the end of a program used when the program is finished running or crashes to print a message to terminal.
Floats & MutabilityRichard briefly discusses that floats in Rust are binary and setting a variable using let means both const and immutable. The keyword mut can be added to make a variable mutable.
Rust Q&ARichard answers student's questions regarding what benefits there are having macros over functions, if there are performance difference between macros and functions, what the point of immutable variables is, and what it means that Rust is a static language.
Numeric Types & Type AnnotationsRichard demonstrates that numeric types cannot be changed to a different variable type and type annotations to be explicit of a variables type. Rust has type inference that will automatically assign a type to a variable and, if it cannot infer a type, the compiler will ask for the type annotation. A student's question regarding if it's possible to change a variable type on the fly is also covered in this segment.
IntegersRichard discusses the different sizes of float sizes including f64 and f32, the different types of integers, integer division, integer sizes, and signed versus unsigned integers. Integers do not have decimals and can be only whole numbers and negative numbers. Students question regarding what Rust's compiler would choose to do with four u8 integers also covered in this segment.
Booleans, Conditionals, Statements, and ExpressionsRichard demonstrates booleans in Rust, the syntax of conditionals, discusses that and expression in Rust is something that evaluates to a value, that a statement does not evaluate to a value, and provides multiple examples for each. The Rust compiler allows the convenience of not using the return keyword only on functions and else if statements ending on an expression.
Statements and Expressions Q&ARichard answers student's questions regarding if the last expression is the return, if a function contains more than one expression can it also be automatically returned by the compiler, and if early returns need to be specified. Student's questions regarding if the type is taken into account in comparisons, if variables of conditional statements if they can be passed around in the string interpolation, and if auto returns can be used for nullish conversion are also covered in this segment.
Primitives Recap and Q&ARichard provides a brief overview of information covered in the first section of the course and opens for student questions. Student questions regarding the difference between traits and macros in Rust, if a return type can be inferred, how to check for libraries that Rust has, and if there are ternary operators are covered in this segment. Additional questions covered include if Rust is compiled into bit code or if it's generated directly into machine code, can binary be cross compiled, if there are queue and stack collections, if a new I64 is created when using something like y as I64, are monoids and monads used in Rust, and if there is any built in crypto.
Primitives ExerciseStudents are instructed to compute population by converting numeric types, compute buildings per person, and print buildings per person to the terminal.
Primitives SolutionRichard live codes the solution to the Primitives exercise. Student questions regarding if there are rules for function order in a single file and how cargo know that it's source is main.rs are also covered in this segment.
TuplesRichard discusses how to define a tuple in Rust, set the values in a tuple to a variable, mutate tuples, and explains what a unit tuple is. Values in a tuple do not have to be the same type and can be set individually or by using destructuring syntax.
StructsRichard demonstrates how to define structs in Rust, destructure a struct, ignore values in a struct, and demonstrates how to define mutable structs. Student's questions regarding what point is being mutated in the example, if the order of the struct matters, and if nested structs can be made are also covered in this segment.
ArraysRichard discusses how to define an array in Rust, how to access values in an array, how to redefine values, and how to iterate over an array. Arrays in must all have the same type and a hardcoded length at compile time. A brief comparison of arrays and tuples is also discussed in this segment.
MemoryRichard discusses the concept of memory being interpreted as a u8 array or a u16 array, how the order of a struct effects the values in memory, and the resulting overhead of arrays, tuples, and stucts.
Collections Recap and Q&ARichard provides a brief overview of the collection section in part 2 including tuples, structs, arrays, and memory. Students questions regarding if functions can be put in a struct, what kind of data iterable structure can be put in different types, if it's possible to make more dynamic arrays, and if structs labels or values can be iterated upon are also covered in this segment.
Collections ExerciseStudents are instructed to add a field to is_costal:bool, return a City described as non-coastal based on a boolean, call a new city, print the description of rustville using string interpolation.
Collections SolutionRichard live codes the solution to the Collections exercise.
Enums & Pattern MatchingRichard demonstrates how to define enums in Rust, set payloads for variants, obtain values using pattern matching, and use pattern matching as an if statement. Rust has no concept of null or undefined, therefore, if pattern matching is used like an if statement every variant must be covered or a compiler error will be thrown.
MethodsRichard discusses how to define methods using the imple keyword and how to use self and Self to infer the impl type. Methods are similar to functions in that they’re declared with the fn keyword and a name, they can take parameters and a return, and they contain code that is run when they're called.
Type ParametersRichard discusses type parameters in Rust, option, and result. Option can be used to avoid errors if the value being altered the function could be nothing or null, while result is used for an operation that might fail.
Pattern Matching Recap and Q&ARichard provides a brief review of enums, pattern matching, methods, type parameters and answers student questions. Student questions regarding what would happen with duplicate matches using pattern matching, if default values can be set in pattern matching, and if there is a way to add additional methods after an impl has been created are covered in this segment.
Pattern Matching ExerciseStudents are instructed to handle the other CitySize variants individually and use City::new() to create a Metropolis-sized city.
Pattern Matching SolutionRichard live codes the solution to the Pattern Matching exercise. Student questions regarding how to create a custom resident count and how to encode values rather than types in the enum varience are also covered in this segment.
VectorsRichard demonstrates how to define a vector or Vec in Rust, increase the vector size, return the length of a vector, usize, and the difference between arrays and vectors. Vectors must have a hard coded type, but do not need a hard coded length.
Stack MemoryRichard discusses stack memory which used to store data for function arguments and return values. A walk through of what happens in memory when function arguments are passed and data is returned is also covered in this segment.
The HeapRichard discusses the function of the heap, gives a walk through of how the heap allocates space, and the differences between the stack and heap.The heap is memory space that is used as seperate storage for the stack. I follows different rules then the stack which allows for more flexibility when handling memory allotment.
Vectors Recap and Q&ARichard provides a review of vectors, usize, stack memory, heap memory, and opens for student questions. Student questions regarding if usize is a pointer, if there is a macro that instanciates and sets capacity at the same time without needing to push, is capacity up to Rust, what to do if the size of a list is unknown, and if it's better to use a linked list data structure are covered in this segment.
Vectors ExerciseStudents are instructed to use .pop() to remove the last city, use .push() to move last_city back into city_names, and print each of the city names.
Vectors SolutionRichard live codes the solution to the Vectors exercise. A student's question regarding why match is needed is also covered in this segment.
Heap BookkeepingRichard briefly provides an overview of part 5 of the course and discusses the process of the alloc function. The alloc function, when called, will take unused heap bytes and mark them as being in-use for later reference.
Rust Memory ManagementRichard discusses how automatic memory management works in Rust, briefly mentions edge cases where automatic deallocation could error, and how functions can be rewritten to safely deallocate memory sooner. Rust will automatically insert the dealloc function when the data is no longer in scope and it's no longer being used.
OwnershipRichard discusses how Rust assigns an owner when it makes an allocation, how return transfers owners, the use-after-move compiler error, and .clone(). A student questions regarding if it's enough to just return the variable is also covered in this segment.
Ownership Recap & Memory ExerciseRichard provides a brief overview of manual memory, automatic memory, ownership, and cloning. Students are then instructed to solve a compiler error, call product(), call average(), and use .clone() or change the function to return a tuple.
Memory SolutionRichard live codes the solution to the Memory exercise. Student questions regarding what sum.0 does, if using an array instead of a vector would bypass the process, and why can you reuse numbers instead of changing it to numbers2 and numbers3 are also covered in this segment.
References & BorrowingRichard demonstrates how to define a reference, which allows access to data without assigning ownership, and a borrow, which temporarily gives a function access to a variable. The borrow checker cannot be turned off in Rust which will throw errors unless references or borrowing is used.
Mutable ReferencesRichard discusses how to designate references as mutable, an example using clear(), and the differences between mutable and immutable references when using let mut. A mutable reference will not take ownership of the data, but will be allowed to mutate the data.
SlicesRichard discusses the reference type slice, vector slices, and string slices. A slice will reference a section of pre-exisiting data on the heap without copying or cloning. A brief review of borrowing, mutable references, slices, and string slices is also covered in this segment.
Borrowing ExerciseStudents are instructed to use references, borrowing, and slices to solve the compiler error, call product(), call average(), and use .clone() or change the function to return a tuple.
Borrowing SolutionRichard live codes the solution to the Borrowing exercise. A students question regarding what would happen if the slice was hard coded and the vector changed is also covered in this segment.
LifetimesRichard discusses how to use the concept of lifetimes to track what's happening in Rust's memory management model. A memory lifetime begins when it's allocated and ends when it is deallocated.
Lifetime AnnotationsRichard demonstrates how to assign lifetime annotations to help keep track of when variables become out of scope. Lifetime annotations can be called anything, but must start with an apostrophe.
Lifetime ElisionRichard discusses that lifetime elision is when the compiler knows the lifetime of a variable and doesn't require annotations. Student questions regarding why the compiler cannot extend a variable's lifetime, why the function call in the example uses all_years and doesn't reference all_years, and what naming conventions are recommended for lifetime annotations are covered in this segment.
The Static Lifetime & Lifetimes RecapRichard discusses the static lifetime and provides a brief review of this segment including lifetimes, lifetime annotations, lifetime elison, and the static lifetime. Static lifetime is defined with an annotation of 'static that notes the variable always exists in the program's binary.
Lifetimes ExerciseStudents are instructed to call sum(), product(), and average() using references, return two slices, and use lifetime annotations to help keep track of the variables.
Lifetimes SolutionRichard live codes the solution to the Lifetimes exercise.
Wrapping UpRichard wraps up the course by summarizing why someone would want to use Rust, providing additional resources for continued learning, and answering some student questions. Student questions regarding next project recommendations, where Rust is best applied, if Actix is a good framework for Rust, and what the job market for Rust looks like.