Learning Rust 1
Introductions
- introductions of two students
Learning Rust, Sections 1 - 3
We are using The Rust Programming Language and rustlings.
Rust is all about memory safety.
Cargo
Rust comes with cargo
to build code and manage dependencies:
cargo new PROJECT
cargo build
cargo build --release
cargo run
cargo check
Mutability
You must declare variables to be mutable. This doesn’t work:
This does:
Shadowing
You can
shadow
a variable by redeclaring it. Curly brackets create a new scope, and variable
declarations go away when they are out of scope. So the below code prints 12
for the inner scope and 6
for the outer scope.
Namespaces
The ::
accesses elements of a namespace. std
is the
Rust standard libary, and is always
available through a use
statement. std::io
is the
io module of the standard lbrary.
The syntax io::stdin()
accesses standard input in the io
module.
Data types and integer overflow
Rust will
infer data types
where possible, but you must explicitly use type annotation where Rust cannot
infer. In the below example, the guess
variables needs a type annotation
because parse()
doesn’t know what type it should be converting to.
Rust has:
- 8-bit to 128-bit signed and unsigned integers, e.g.
i16
,u32
- floating-point types, e.g.
f32
,f64
- boolean type,
bool
, which can betrue
orfalse
- character type,
char
Rust also has
- tuples
- arrays
For integer overflow, Rust provides wrappers for:
wrapping_
— wrapschecked_
— returns None if overflowoverflowing
— returns the value and True if overflowsaturating
— caps at max or min value
Return values
Rust will return the value of the last expression (leave off the semicolon!):
You can also use an explicit return
.
Exercises
At this point, you are ready to complete exercises for sections 0-3, plus the first quiz.
Learning Rust, Section 4
Ownership
To preserve memory safety, Rust uses a set of ownership rules.
Each value in Rust has an owner.
There can only be one owner at a time.
When the owner goes out of scope, the value will be dropped.
This is OK, because the variables are on the stack:
There are two variables, and each have the value 5.
This is not OK, because Rust does not want two references to the same memory on the heap:
When s1
and s2
go out of scope, Rust would try to free the memory twice,
resulting in a
double free
error.
So, to solve this problem, Rust declares that s1
is no longer in scope. Thus
only s2
is valid.
If your code really needs two pointers to two copies of the same string, use
clone()
:
Ownership and functions
When a value is passed to a function, its ownership is moved into the function, unless the type is one that can be copied. Types that can be copied: integers, floats, booleans (true and false), and char.
Return values and scope
Rust functions can take ownership and return ownership.
Notice how you do not need to call a function to free memory! Scoping rules take care of it for you.
References
Use a reference when you want to allow a function to use a variable without claiming ownership of it. This is called borrowing.
A reference is like a pointer, but guaranteed to be valid.
A function cannot modify a reference:
You can make a reference mutable:
If you have a mutable reference to a value, you can have no other references to that value.
So this is not allowed:
This prevents data races! The Rust book has a good definition of when data races occur:
- Two or more pointers access the same data at the same time.
- At least one of the pointers is being used to write to the data.
- There is no mechanism being used to synchronize access to the data.
Rust will refuse to compile code with data races.
At any given time, you can have either one mutable reference or any number of immutable references.
References must always be valid.
Exercises
At this point, you are ready to complete exercises for section 4, on primitive types and section 6, on move semantics.
Learning Rust, Section 5
Structs
Structs let you define custom types:
Here is how you initialize a struct:
See the book for additional details.
You can also
define methods on structs
using impl
:
You can also define associated functions on structs. These are functions that don’t take a struct, but return one.
Exerises
Complete exerises for section 7, on structs.