# Rust
## Getting started
installing rust
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
getting the latest version of Rust
```
rustup update
```
creating a new project
```sh
cargo new <project-name>
```
running a project
```sh
cargo run
cargo run -q
```
adding a dependency to current project. You can find all crates(==Package) at
[crates.io](https://crates.io/) and the documentation is at
[docs.rs](https://docs.rs/)
```sh
cargo add <crate-name>
```
Every crate has a root module and might have some additional submodules. They are
used to better organize our codebase.
If you want to use modules in your project, the way to access functions in those
modules is by referring to those modules at the top of the code where you want to
use it, using the keyworkd `mod`. Like this:
```rust
mod games;
fn main(0 {
let deck = games::Deck::new();
let deck = games::cards::Deck::new(); // if Deck is inside a submode called
cards within the modeule games.
}
```
For using external crates you follow the same sintaxis.
```rust
let rng = rand::thread_rng();
let rand_u64 = rand::rngs::OsRng.next_u64();
```
or you can use a shorter version of the above like this:
```rust
use rand::thread_rng;
use rand::rngs::OsRng
fn main() {
let rng = thread_rng();
let rand_u64 = next_u64();
}
```
Or
```rust
use rand::{thread_rng, rngs::OsRng};
```
installing dependencies
```sh
cargo build
```
This creates a `Cargo.lock`. This file is a log of the exact versions of the
dependencies we are using locally.
### Variables
In Rust, variable are immutable by default, cannot change values.
```rust
let numbers = vec![];
let mut numbers = vec![];
```
### Arrays vs Vectors
Arrays are fixed in size. Vector are dynamic (grow / shrink)
```rust
let suits = ["Diamonds", "Clubs"]
let suits = vec!["Diamonds", "Clubs"]
```
Adding new elements
```rust
let mut vec = vec![1, 2, 3];
vec.push(4); // vec is now [1, 2, 3, 4]
```
Extending a vector with another collection
```rust
let mut vec = vec![1, 2, 3];
let more_elements = [4, 5, 6];
vec.extend(&more_elements); // vec is now [1, 2, 3, 4, 5, 6]
```
Inserting Elements at a Specific Position
```rust
let mut vec = vec![1, 2, 4, 5];
vec.insert(2, 3); // Insert 3 at index 2
```
Appending One Vector to Another
```rust
let mut vec1 = vec![1, 2, 3];
let mut vec2 = vec![4, 5, 6];
vec1.append(&mut vec2); // vec1 is now [1, 2, 3, 4, 5, 6]
println!("vec1: {:?}", vec1);
println!("vec2: {:?}", vec2); // vec2 is now empty
```
Converting an Array to a Vector
```rust
let arr = [1, 2, 3];
let mut vec = arr.to_vec(); // Convert array to vector
```
### Inherit Implementations
This is a fancy name to add a function to an Struct.
```rust
struct Deck {
cards: Vec<String>,
}
impl Deck {
fn new() -> Self { //associated function
// do things
}
fn shuffle(&self) { // method
// do things
}
}
fn main() {
let deck = Deck::new();
deck.shuffle();
}
```
- Associated functions: when you want to add functionality not tied to an specific
instance.
- Method: whne you need to read/change fields on a specific functions using
`&self`.
Note: in `Rust` there is a concept of implicit return, there is not need to
explicitly use `return`, instead you can just write the value/variable you want to
return as the last executable statement without the `;`.
### Ownership, Borrowing and Lifetimes
These 3 concepts may represent 90% of the difficulty of `Rust`.
<img width="1156" alt="image"
src="https://gist.github.com/user-attachments/assets/96ff2d9a-a699-4d61-bc3b-
9b3de3bada63">
**Ownership:** The goal of ownership is to limit the ways you can reference and
change data.
- Multiple things can refer to a value at the same time, but they are all read
only. Rule 3, 5 and 6 above.
- A value can only be updated when there are no read-only references to it. Rule 1,
5 and 6 above.
Above all, `Rust` wants to avoid 'unexpected updates'.
This is the correct (manually) way to pass values to funcvtions, in any other way,
the value will be moved to the function `print_account` and `account` will contain
no value.
```rust
fn print_account(account: Account) -> Account {
println!("{:#?}", account);
account
}
fn main() {
let mut account = Account::new(1, String::from("Rochy"));
account = print_account(account); // We are temporaruily assigning account to
the fn but the ownership it's returned.
account = print_account(account);
}
```
**Borrowing:** By using Borrowing what we do is creating references (using the
special operator `&`) to variables so you don't move the value, you just share the
refernce of the owner of the value.
```rust
fn print_account(account: &Account) {
println!("{:#?}", account);
}
fn main() {
let account = Account::new(1, String::from("Rochy"));
account = print_account(&account); // send the reference to the owner of the
value
account = print_account(&account); // now the value can used in multiple
places, value is not moved
}
```
Writable/Mutable reference. We use the `&mut` operator. They allow us to
read/change a value without moving it. Rules 5 and 6 listed above.
```rust
fn change_account(account: &mut Account) {
account.balance = 10;
}
fn main() {
let myt account = Account::new(...);
change_account(&mut account);
}
```
**Note:** Some types of values are copied instead of moved. All numbers, bool,
char, Arrays, Tuples and references (readble or writeable).
**Lifetimes**: refers to how long an owner/reference exists
**Generic/Annotations Lifetimes**: extra syntax added in to clarify relationship
between different lifetimes.
With every **function** we write, we need to think about whether we are receiving
values or refs.
<img width="1246" alt="image"
src="https://gist.github.com/user-attachments/assets/e8701619-34d3-4513-90ba-
6c5883c51547">
- need to store teh argument somewhere? taking ownership, receieve a value
- need to do a calculation with the value? read-only ref
- need to change the vale in some way? mutable ref
### Enums
<img width="1278" alt="image"
src="https://gist.github.com/user-attachments/assets/31b02b22-4ae2-46ad-8ac2-
e46076ff18bb">
```rust
#[derive(Debug)]
enum Media {
Book { title: String, author: String},
Movie { title: String, director: String},
Audiobook { title: String},
}
impl Media {
fn description(&self) -> String {
if let Media::Book {title, author} = self {
format!("Book: {} written by {}", title, author)
} else if let Media::Movie {title, director} = self {
format!("Movie: {} directed by {}", title, director)
} else if let Media::Audiobook {title} = self {
format!("Audiobook: {}", title)
} else {
String::from("No valid media!")
}
fn main() {
let movie = Media::Movie { title: String::from("Aliens"), director:
String::from("Good Director") };
print!("{}", movie.description());
}
```
- We can imagine this creates 3 structs
- All of them are the of type `Media`
- We can define a fn that accepts the type `Media` but passes Book or Movie or
Audiobook
Or we use pattenr matching
```rust
fn description(&self) -> String {
match self {
Media::Book {title, author} => {
format!("Book: {} written by {}", title, author)
}
Media::Movie {title, director} => {
format!("Movie: {} directed by {}", title, director)
}
Media::Audiobook {title} => {
format!("Audiobook: {}", title)
}
}
}
```
<img width="978" alt="image"
src="https://gist.github.com/user-attachments/assets/019de334-2095-4436-bbc1-
f8d11a7d4c3e">
<img width="1356" alt="image"
src="https://gist.github.com/user-attachments/assets/f1c2687e-9495-497d-826f-
8a1504fdad0b">
There are other more compact ways to deal with `Option`, however using `match` is
the recommended one.
<img width="1312" alt="image"
src="https://gist.github.com/user-attachments/assets/16602e3b-1ecd-41eb-8511-
ad4c9eb28cd1">