An open API service indexing awesome lists of open source software.

https://github.com/ladroid/rustcheatsheet


https://github.com/ladroid/rustcheatsheet

programming rust rust-cheat rust-lang

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

          

# Cheat sheet Rust

Table of Content

- [Cheat sheet Rust](#cheat-sheet-rust)
* [First](#first)
* [Second](#second)
* [Third](#third)
* [Fourth](#fourth)
* [Fifths](#fifths)
* [Sixth](#sixth)
* [Seventh](#seventh)
* [Eighths](#eighths)
* [Ninths](#ninths)
* [Tenths](#tenths)
* [Eleventh](#eleventh)
* [Twelvfth](#twelvfth)
* [Thirteenth](#thirteenth)
* [Fourteenth](#fourteenth)
* [Fifteenth](#fifteenth)
* [Sixteenth](#sixteenth)
* [Seventeenth](#seventeenth)
* [Eighteenth](#eighteenth)
* [Nineteenth](#nineteenth)
* [Twenties](#twenties)
* [Twenty first](#twenty-first)
* [Twenty second](#twenty-second)
* [Advanced](#advanced)
* [First](#first-1)
* [Second](#second-1)
* [Rust's Standard Concurrency Mechanisms:](#rust-s-standard-concurrency-mechanisms-)
+ [1. **Threads**](#1---threads--)
+ [2. **Mutex (Mutual Exclusion)**](#2---mutex--mutual-exclusion---)
+ [3. **Rc (Reference Counting) and Arc (Atomic Reference Counting)**](#3---rc--reference-counting--and-arc--atomic-reference-counting---)
+ [4. **Channels**](#4---channels--)
+ [5. **Barriers**](#5---barriers--)

------

## First

Let's get started with a simple "Hello, World!" program in Rust.

First, make sure that you have Rust installed on your machine. If not, you can download it from the official website (https://www.rust-lang.org/tools/install) and install it following the given instructions.

Once Rust is installed, you can create a new Rust file using any text editor you prefer. Save it with the `.rs` extension, for example, `main.rs`. Then, write the following code:

```rust
// This is your first Rust program!

fn main() {
// Print "Hello, World!" to the console
println!("Hello, World!");
}
```

Here's a breakdown of what's happening in the code:

- `fn main() {}`: The main function. This is a special function where your program starts running.
- `println!()`: A macro (not a function) that prints text to the console. You can recognize macros by the `!` at the end.
- `"Hello, World!"`: A string, which we are passing to `println!()` to print.

To run the program, open a terminal, navigate to the directory where you saved your file, and use the `rustc` compiler to compile the source code into an executable:

```bash
rustc main.rs
```

This will create a new executable in the same directory. You can run it with:

```bash
./main
```

The output will be:

```
Hello, World!
```

Congratulations! You've written and run your first Rust program.

## Second
Let's build on what we learned in the first tutorial. We'll explore variables and basic types in Rust.

Create a new Rust file called `variables.rs` and write the following code:

```rust
fn main() {
// Declare a variable
let greeting = "Hello, Rust!";
println!("{}", greeting);

// Declare a mutable variable
let mut counter = 5;
println!("Counter: {}", counter);

// Modify the mutable variable
counter = 10;
println!("Counter: {}", counter);

// Constants
const MAX_VAL: u32 = 100_000;
println!("Max Value: {}", MAX_VAL);

// Shadowing
let x = 5;
let x = x * 2;
let x = x + 10;
println!("x: {}", x);
}
```

Here's a breakdown of what's happening:

- `let greeting = "Hello, Rust!";` Here, we're declaring an immutable variable called `greeting` that holds a string.
- `let mut counter = 5;` `mut` keyword makes `counter` a mutable variable, meaning its value can be changed.
- `counter = 10;` We're changing the value of `counter` here.
- `const MAX_VAL: u32 = 100_000;` This declares a constant `MAX_VAL`. Constants are always immutable and you need to declare the type of the value.
- In the shadowing section, we redeclare `x` twice. Each time, a new variable `x` is created and gets the value of the old `x` modified. The final value of `x` is `20`.

Compile and run this program as you did in the previous tutorial. You'll see the values of the variables printed to the console.

## Third
Let's now move on to control flow with conditionals and loops in Rust. This tutorial will focus on `if/else` statements, `match` statements, and a few types of loops.

Create a new Rust file called `control_flow.rs` and write the following code:

```rust
fn main() {
let num = 10;

// If/else statement
if num < 10 {
println!("The number is less than 10.");
} else {
println!("The number is 10 or greater.");
}

// Match statement
match num {
0 => println!("The number is zero."),
1..=9 => println!("The number is between 1 and 9."),
_ => println!("The number is 10 or greater."),
}

// Loop
let mut counter = 0;
loop {
counter += 1;
if counter > 5 {
break;
}
println!("Loop count: {}", counter);
}

// While loop
counter = 0;
while counter < 5 {
counter += 1;
println!("While loop count: {}", counter);
}

// For loop
for num in 1..6 {
println!("For loop count: {}", num);
}
}
```

Here's a breakdown of the code:

- `if num < 10` checks if the variable `num` is less than 10. If it is, it executes the first branch and prints "The number is less than 10.". If it's not, it executes the `else` branch and prints "The number is 10 or greater.".
- `match num` checks the value of `num` and executes the branch that matches it. `_` is a catch-all pattern that matches any value.
- The `loop` keyword creates an infinite loop. `break` is used to exit the loop when `counter > 5`.
- The `while` loop executes as long as `counter < 5` is true.
- The `for` loop iterates over the range `1..6`, which includes `1, 2, 3, 4, 5`.

Compile and run this program to see control flow in action in Rust.

## Fourth
Let's delve into Rust functions. Functions are at the heart of Rust, as they are used to structure and reuse code. We will look at defining and calling functions, parameters, return values, and higher order functions.

Create a new Rust file called `functions.rs` and write the following code:

```rust
// Define a function
fn greet() {
println!("Hello, Rust!");
}

// Define a function with parameters
fn greet_person(name: &str) {
println!("Hello, {}!", name);
}

// Define a function with a return value
fn add(a: i32, b: i32) -> i32 {
a + b // no semicolon, so this is an expression that gets returned
}

// Define a higher order function
fn apply(f: F, x: i32, y: i32) -> i32
where
F: Fn(i32, i32) -> i32,
{
f(x, y)
}

fn main() {
// Call a function
greet();

// Call a function with parameters
greet_person("Alice");

// Call a function with a return value
let sum = add(5, 7);
println!("5 + 7 = {}", sum);

// Call a higher order function
let product = apply(|a, b| a * b, 5, 6); // pass in a closure that multiplies
println!("5 * 6 = {}", product);
}
```

Here's what's happening in the code:

- `greet` is a simple function with no parameters and no return value. It's called in `main` with `greet()`.
- `greet_person` has one parameter, a string slice (`&str`). It's called with the string `"Alice"`.
- `add` has two `i32` parameters and returns their sum, also an `i32`. Note that the last line doesn't have a semicolon, so it's an expression and its value gets returned.
- `apply` is a higher order function. It takes a function `f` as a parameter, as well as two `i32` values, and it applies `f` to those values.
- In `main`, `apply` is called with a closure `|a, b| a * b`, which multiplies its arguments, and the numbers `5` and `6`.

Compile and run this program to see how functions work in Rust. By the end of this tutorial, you should have a solid understanding of how to define and use functions in Rust.

## Fifths
Let's explore Rust's data structures - structs and enums.

Structs are similar to objects in JavaScript or classes in languages like Java and C++, while enums allow you to define a type by enumerating its possible variants.

Create a new Rust file called `data_structures.rs` and write the following code:

```rust
// Define a struct
struct Point {
x: f64,
y: f64,
}

// Define a function that takes a Point
fn print_point(point: Point) {
println!("Point at ({}, {})", point.x, point.y);
}

// Define an enum
enum Direction {
North,
South,
East,
West,
}

// Define a function that takes a Direction
fn print_direction(direction: Direction) {
match direction {
Direction::North => println!("We're heading North!"),
Direction::South => println!("We're heading South!"),
Direction::East => println!("We're heading East!"),
Direction::West => println!("We're heading West!"),
}
}

fn main() {
// Instantiate a Point
let p = Point { x: 5.0, y: 7.0 };
print_point(p);

// Use an enum
let dir = Direction::North;
print_direction(dir);
}
```

Here's what's happening in the code:

- `Point` is a struct with two fields, `x` and `y`, both of type `f64`.
- `print_point` is a function that takes a `Point` as a parameter and prints its coordinates.
- `Direction` is an enum with four variants: `North`, `South`, `East`, `West`.
- `print_direction` is a function that takes a `Direction` and uses a `match` statement to print a different message for each possible variant.
- In `main`, we create a `Point` and a `Direction` and pass them to `print_point` and `print_direction`, respectively.

Compile and run this program to see how structs and enums work in Rust. After this tutorial, you should be familiar with defining and using basic data structures in Rust.

## Sixth
In this tutorial, we will discuss Rust's ownership, borrowing, and lifetimes, which are central to Rust's memory safety guarantees.

Create a new Rust file called `ownership.rs` and write the following code:

```rust
fn main() {
// Ownership and functions
let s = String::from("hello"); // s comes into scope
takes_ownership(s); // s's value moves into the function and is no longer valid here

let x = 5; // x comes into scope
makes_copy(x); // x would move into the function, but i32 is Copy, so it's ok to still use x afterward

// Borrowing
let s = String::from("hello");
no_take_ownership(&s); // s is borrowed, not owned

// Mutable borrowing
let mut s = String::from("hello");
change(&mut s); // mutable borrowing
println!("{}", s);

// Lifetimes
let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
let smallest = smallest_string(&string1, &string2);
result = smallest;
}
println!("Smallest string: {}", result);
}

fn takes_ownership(some_string: String) {
println!("{}", some_string);
} // some_string goes out of scope and `drop` is called

fn makes_copy(some_integer: i32) {
println!("{}", some_integer);
} // some_integer goes out of scope. Nothing special happens.

fn no_take_ownership(some_string: &String) {
println!("{}", some_string);
} // some_string goes out of scope. Nothing special happens.

fn change(some_string: &mut String) {
some_string.push_str(", world");
}

fn smallest_string<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() < y.len() {
x
} else {
y
}
} // Returns a reference to the smallest string
```

Here's what's happening in the code:

- `takes_ownership` takes ownership of a `String`. After it's called, the passed `String` can no longer be used.
- `makes_copy` takes an `i32`, which is `Copy`. This means that the integer data gets copied and the original can still be used.
- `no_take_ownership` and `change` illustrate borrowing. `&s` allows you to create a reference to `s`, but not take ownership. `&mut s` is a mutable reference.
- `smallest_string` shows how lifetimes work. Lifetimes ensure that any reference to an object will not outlive the object itself.

Compile and run this program to see how ownership, borrowing, and lifetimes work in Rust. By the end of this tutorial, you should have a basic understanding of these concepts, which are fundamental to Rust's design.

## Seventh
In this tutorial, we will explore error handling in Rust, which is a key aspect of any robust program. Specifically, we will look at Rust's `Result` type, which can be used for functions that might fail.

Create a new Rust file called `error_handling.rs` and write the following code:

```rust
use std::num::ParseIntError;

// This function may fail if the string cannot be parsed into an integer
fn parse_number(s: &str) -> Result {
s.parse()
}

fn main() {
match parse_number("10") {
Ok(num) => println!("It's a number: {}", num),
Err(e) => println!("Error: {}", e),
}

match parse_number("ten") {
Ok(num) => println!("It's a number: {}", num),
Err(e) => println!("Error: {}", e),
}

// You can also use the `?` operator to propagate the error up
let number = match "10".parse::() {
Ok(num) => num,
Err(e) => return Err(e.into()), // convert ParseIntError into a Box
};
println!("Number: {}", number);
}
```

Here's what's happening in the code:

- The `parse_number` function takes a string and tries to parse it into an integer. If this fails, it returns an error.
- In `main`, we call `parse_number` twice: once with a string that can be parsed into a number, and once with a string that can't. In each case, we use a `match` statement to handle the `Ok` and `Err` cases.
- The `?` operator can be used to propagate errors. If the expression before `?` is an `Err`, it will return from the current function and give the error to the caller. If it's `Ok`, it will take the value out of `Ok` and continue the code. Note: The `?` operator can be used in functions that return a `Result` (or `Option`). It can't be used in the `main` function directly.

Compile and run this program to see how error handling in Rust works. After this tutorial, you should have a basic understanding of the `Result` type and how to use it for error handling.

## Eighths
In this tutorial, we'll dive into modules and packages in Rust. These tools allow you to structure and organize large projects. Additionally, we will touch on `pub` keyword and `use` declaration.

Create a new directory for your project:

```bash
cargo new modules_and_packages
cd modules_and_packages
```

Then, add a new file named `lib.rs` in the `src` directory of your project:

`src/lib.rs`
```rust
// Define a module named "greetings"
mod greetings {
// By default, everything is private in Rust. The `pub` keyword makes it accessible outside this module.
pub fn hello() {
println!("Hello from the greetings module!");
}
}

// Use the `greetings` module
pub use greetings::hello;
```

Next, modify the `src/main.rs` file:

`src/main.rs`
```rust
// Import our library. This would be the name of your crate.
extern crate modules_and_packages;

// Use the `hello` function from our library
use modules_and_packages::hello;

fn main() {
// Call the `hello` function
hello();
}
```

Now, from your terminal, in the `modules_and_packages` directory, run:

```bash
cargo run
```

You should see the output: "Hello from the greetings module!"

Here's a summary:

- Modules allow you to group related definitions together and make them reusable.
- The `pub` keyword makes items public, allowing them to be accessible outside their module.
- `use` allows you to bring items into scope, making it easier to reference them in your code.
- `extern crate` brings an external crate into your project, making its items accessible. (Note: With the 2018 edition of Rust, `extern crate` is often no longer needed, as it's implicitly added by Cargo. But it's good to know about in case you come across it in older Rust code.)

By the end of this tutorial, you should understand how to use modules to organize your code and how packages and crates work in Rust.

## Ninths
In this tutorial, we'll dive into iterators and closures in Rust. Both are powerful features of Rust that enable functional programming patterns.

**Iterators** allow you to process a sequence of elements.
**Closures** are anonymous functions that you can store in a variable or pass as arguments to other functions.

Let's get started:

Create a new Rust file named `iterators_and_closures.rs` and write the following code:

```rust
fn main() {
// Closures
let add = |x, y| x + y;
println!("5 + 3 = {}", add(5, 3));

let numbers = vec![1, 2, 3, 4, 5];

// Iterators
// Using `map` to transform each element in the iterator
let doubled: Vec<_> = numbers.iter().map(|x| x * 2).collect();
println!("Doubled numbers: {:?}", doubled);

// Using `filter` to select certain items
let evens: Vec<_> = numbers.iter().filter(|&&x| x % 2 == 0).collect();
println!("Even numbers: {:?}", evens);

// Using `find` to get the first match
let first_greater_than_three = numbers.iter().find(|&&x| x > 3);
match first_greater_than_three {
Some(val) => println!("First number greater than 3: {}", val),
None => println!("No number greater than 3 found"),
}
}

```

Here's a breakdown of the code:

- **Closures**: We define a simple closure `add` that takes two parameters and returns their sum. Closures are defined using `|...| {...}` syntax.

- **Iterators**: We have a `Vec` named `numbers`. Using the iterator methods `map`, `filter`, and `find`, we can transform, select, or search the numbers, respectively.

- `map`: Applies a function to each item and collects the results into a vector.
- `filter`: Filters items based on a predicate (a function returning `bool`).
- `find`: Returns the first item that matches a predicate.

Compile and run the program to explore the workings of iterators and closures in Rust. After this tutorial, you should understand how to use these powerful tools in your Rust programs to enable more functional programming patterns.

## Tenths
In this tutorial, we'll delve into `struct` methods and associated functions, as well as the concept of lifetimes in Rust. Both are crucial aspects of the language that further its expressiveness and safety.

**Struct Methods and Associated Functions**
Methods are similar to functions, but they are associated with a specific instance of a type (like a struct or enum). Associated functions are similar to static methods in other languages, and they don't take an instance.

**Lifetimes**
Lifetimes are a way of expressing the scope of validity of references within Rust code. They ensure that references don't outlive the data they point to.

Let's explore:

Create a new Rust file named `methods_lifetimes.rs` and write the following code:

```rust
struct Circle {
radius: f64,
}

impl Circle {
// Associated function (like static methods in other languages)
fn new(radius: f64) -> Circle {
Circle { radius }
}

// Method (works on an instance)
fn area(&self) -> f64 {
3.14159265358979323846 * self.radius * self.radius
}
}

// A function with lifetimes
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() {
s1
} else {
s2
}
}

fn main() {
let circle = Circle::new(5.0); // Call associated function
println!("Circle area: {}", circle.area()); // Call method

let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
result = longest(&string1, &string2);
}
println!("Longest string: {}", result);
}
```

Key points in the code:

- **Circle Struct**: This represents a geometric circle with a defined radius.

- **impl Block**: Within this block, methods and associated functions related to the Circle struct are defined.

- `new`: An associated function that returns a new instance of `Circle`.
- `area`: A method that calculates the area of the circle. `&self` refers to the instance the method is called on.

- **longest Function**: This function determines the longest of two string slices. It uses lifetimes (`'a`) to indicate that the returned reference has the same lifetime as the shortest of the two input lifetimes.

Compile and run the code. By the end of this tutorial, you should have a grasp on struct methods, associated functions, and a basic understanding of lifetimes in Rust.

## Eleventh
In this tutorial, we'll look into enums and pattern matching in Rust. Enums (short for "enumerations") are a way to represent data that can be one of several possible variants. Pattern matching is an elegant way to handle such data.

**Enums**
Enums are similar to "sum types" in other languages. In Rust, they are a powerful construct that can hold data in their variants.

**Pattern Matching**
Pattern matching is a feature that lets you destructure and match on the data held in data structures, including enums.

Let's dive in:

Create a new Rust file named `enums_patterns.rs` and write the following code:

```rust
// Define an enum to represent a web event
enum WebEvent {
PageLoad,
PageUnload,
KeyPress(char),
Click { x: i64, y: i64 },
}

// Function to process a web event
fn process_event(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("Page loaded!"),
WebEvent::PageUnload => println!("Page unloaded!"),
WebEvent::KeyPress(c) => println!("Key '{}' pressed!", c),
WebEvent::Click { x, y } => println!("Clicked at x={}, y={}", x, y),
}
}

fn main() {
let pressed_key = WebEvent::KeyPress('x');
let click_position = WebEvent::Click { x: 20, y: 80 };

process_event(pressed_key);
process_event(click_position);
}
```

Here's the breakdown:

- **WebEvent Enum**: This enum represents different types of web events. Some variants hold data, like `KeyPress`, which has a char, and `Click`, which has two `i64` values.

- **process_event Function**: This function takes a `WebEvent` as an argument. It uses the `match` keyword to perform pattern matching on the event, executing different code depending on the event type.

- **main Function**: We create two instances of `WebEvent` and pass them to `process_event` to see the pattern matching in action.

Compile and run the program to see how enums and pattern matching work together. By the end of this tutorial, you should understand how to define enums, store data in their variants, and use pattern matching to handle different enum variants.

## Twelvfth
Certainly! In this tutorial, we'll focus on **traits** and **generics** in Rust. Both of these concepts are pivotal to writing reusable and flexible code.

**Traits**
A trait is a way to define shared behavior across types. Think of them as similar to interfaces in other languages.

**Generics**
Generics let you write a data type or function that is abstracted over types, ensuring type safety.

Let's proceed:

Create a new Rust file named `traits_generics.rs` and write the following code:

```rust
// Define a trait named `Printable`
trait Printable {
fn format(&self) -> String;
}

// Implement `Printable` for `i32`
impl Printable for i32 {
fn format(&self) -> String {
format!("i32: {}", *self)
}
}

// Implement `Printable` for `String`
impl Printable for String {
fn format(&self) -> String {
format!("String: {}", *self)
}
}

// A generic function that takes a `Printable` type
fn print_it(item: T) {
println!("{}", item.format());
}

fn main() {
let my_string = String::from("Hello");
let my_int = 5;

print_it(my_string);
print_it(my_int);
}
```

Here's an overview:

- **Printable Trait**: This trait contains a single method `format` which returns a `String`.

- **Implementing the Trait**: We implement `Printable` for both `i32` and `String`. Each type provides its custom behavior for the `format` method.

- **print_it Function**: This is a generic function. The `` syntax means "for some type `T` that implements the `Printable` trait." The function can then call the `format` method on its argument, ensuring it's compatible with any `Printable` type.

- **main Function**: We create a `String` and an `i32`, then pass them to `print_it`, demonstrating the function's generic behavior.

When you compile and run the program, you will see how the same function, `print_it`, can operate on different types, thanks to traits and generics.

After completing this tutorial, you should be familiar with how to define traits, implement them for various types, and create generic functions that operate on trait-bounded types. This will enable you to write more reusable and type-safe Rust code.

## Thirteenth
In this tutorial, we'll explore **error handling** in Rust. Rust takes a unique approach to handle errors by using types to represent success and failure, rather than relying on exceptions as many other languages do.

The two primary error-handling types in Rust are `Option` and `Result`.

**Option**
The `Option` type expresses the possibility of absence. It's an enum with two variants: `Some(T)` and `None`.

**Result**
The `Result` type is used for functions that can fail. It's an enum with two variants: `Ok(T)` for success and `Err(E)` for errors.

Let's dive in:

Create a new Rust file named `error_handling.rs` and write the following code:

```rust
// Function that might fail, returning an Option
fn divide(numerator: f64, denominator: f64) -> Option {
if denominator == 0.0 {
None
} else {
Some(numerator / denominator)
}
}

// Function that might fail, returning a Result
fn sqrt(number: f64) -> Result {
if number < 0.0 {
Err("Cannot take the square root of a negative number.".to_string())
} else {
Ok(number.sqrt())
}
}

fn main() {
match divide(5.0, 0.0) {
Some(result) => println!("Division result is {}", result),
None => println!("Cannot divide by zero"),
}

match sqrt(-9.0) {
Ok(result) => println!("Square root is {}", result),
Err(error) => println!("Error: {}", error),
}
}
```

Key Points:

- **divide Function**: This function returns an `Option`. It checks if the denominator is zero and returns `None` if it is, indicating the absence of a valid value.

- **sqrt Function**: This function returns a `Result`. It checks if the number is negative and, if so, returns an `Err` with an error message. Otherwise, it returns the square root inside an `Ok`.

- **main Function**: Here, we use pattern matching with `match` to handle the potential values (or errors) returned by our functions.

When you compile and run the program, you'll see how Rust handles errors in a type-safe manner, providing clear paths for success and failure scenarios.

After this tutorial, you should understand how to use `Option` and `Result` to gracefully handle errors in Rust, making your code robust and readable.

## Fourteenth
In this tutorial, we'll explore **modules** and **visibility** in Rust. These concepts are essential for organizing code and creating reusable libraries.

**Modules**
Modules allow you to organize code into separate namespaces, facilitating code reuse and readability.

**Visibility**
Rust provides a powerful system to control the visibility of items (functions, structs, etc.) with the `pub` keyword, ensuring encapsulation.

Let's dive in:

Create a new Rust file named `modules_visibility.rs` and write the following code:

```rust
// Define a module named "math"
mod math {
// Private function (not accessible outside the module)
fn add(a: i32, b: i32) -> i32 {
a + b
}

// Public function (accessible outside the module)
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}

// Public nested module
pub mod advanced {
pub fn power(base: i32, exponent: i32) -> i32 {
(0..exponent).fold(1, |acc, _| acc * base)
}
}
}

fn main() {
// Accessing the public function from the math module
println!("5 * 3 = {}", math::multiply(5, 3));

// Accessing the public function from the nested module
println!("2 power 3 = {}", math::advanced::power(2, 3));

// This line would cause a compile error, because the `add` function is private
// println!("5 + 3 = {}", math::add(5, 3));
}
```

Key Points:

- **math Module**: We've defined a module named `math`. Inside this module, we have two functions: a private function `add` and a public function `multiply`.

- **advanced Submodule**: Within the `math` module, we've defined another module named `advanced`. It has a public function `power`.

- **main Function**: Here, we're accessing the functions from the `math` module and its submodule `advanced`. You'll notice that we commented out the call to the `add` function since it's private and cannot be accessed outside its module.

Compile and run the program. You'll see how modules in Rust allow you to organize and encapsulate your code, making it more maintainable and reusable.

After this tutorial, you should understand the basics of creating modules in Rust and controlling the visibility of items within those modules. This will be invaluable when you start building larger projects or libraries.

## Fifteenth
In this tutorial, we'll explore **closures** and **higher-order functions** in Rust. Closures are a powerful feature, allowing you to capture variables from the surrounding environment. Higher-order functions are functions that take other functions (or closures) as arguments or return them.

**Closures**
Closures in Rust look like lambda functions or anonymous functions in other languages. They can capture values from their environment.

**Higher-order Functions**
Functions that can take other functions as parameters or return functions.

Let's dive in:

Create a new Rust file named `closures_hof.rs` and write the following code:

```rust
// A function that returns a closure
fn multiplier(factor: i32) -> impl Fn(i32) -> i32 {
|number| number * factor
}

// A higher-order function that applies a function to a value
fn apply(func: F, value: i32) -> i32
where
F: Fn(i32) -> i32,
{
func(value)
}

fn main() {
// Simple closure that captures the `factor` variable
let factor = 3;
let triple = |x| x * factor;

println!("Triple of 5 is: {}", triple(5));

// Using a function that returns a closure
let double = multiplier(2);
println!("Double of 5 is: {}", double(5));

// Using a higher-order function
println!("Triple of 7 using apply: {}", apply(triple, 7));
}

```

Key Points:

- **triple Closure**: We define a simple closure that triples its input. It captures the `factor` variable from the surrounding environment.

- **multiplier Function**: This function returns a closure. The returned closure multiplies its input by the given `factor`.

- **apply Function**: This is a higher-order function that takes a function `func` as a parameter and an `i32` value, then applies the function to the value.

- **main Function**: We demonstrate using the `triple` closure, the closure returned by `multiplier`, and the higher-order function `apply`.

Compile and run the program. Closures and higher-order functions allow for concise, expressive, and flexible code in Rust.

After this tutorial, you should have a foundational understanding of closures in Rust, how they can capture their environment, and how to utilize higher-order functions for more flexible code patterns.

## Sixteenth
In this tutorial, we'll delve into **concurrency** in Rust. Concurrency is about executing multiple tasks at the same time, and Rust offers several tools to manage concurrent code safely.

We'll particularly explore **threads** in this tutorial.

**Threads**
Threads allow multiple operations to run in parallel. However, concurrent programming can introduce various pitfalls if not handled correctly. Rust’s type system and ownership rules play a significant role in getting concurrency right.

Let's get started:

Create a new Rust file named `concurrency_threads.rs` and write the following code:

```rust
use std::thread;
use std::time::Duration;

// A simple function that simulates a heavy computation
fn heavy_calculation(number: i32) -> i32 {
println!("Computing for number {}", number);
thread::sleep(Duration::from_secs(2));
number * number
}

fn main() {
// Spawn a new thread to run the heavy_calculation function
let handle = thread::spawn(|| {
let result = heavy_calculation(5);
println!("Result from thread: {}", result);
});

// Do some work in the main thread as well
for i in 1..5 {
println!("Main thread working on: {}", i);
thread::sleep(Duration::from_millis(300));
}

// Wait for the spawned thread to finish
handle.join().unwrap();
}
```

Key Points:

- **heavy_calculation Function**: This function simulates a computation that takes a couple of seconds.

- **thread::spawn**: This spawns a new thread. The code inside the closure will be executed in this new thread.

- **handle.join()**: This ensures the main thread waits for the spawned thread to finish before exiting.

- **main Function**: Here, we spawn a new thread to run `heavy_calculation` while the main thread continues with its loop. Both operations occur concurrently.

Compile and run the program. You'll notice the main thread and the spawned thread run concurrently, showcasing basic multi-threading in Rust.

After this tutorial, you should have a basic understanding of how to use threads in Rust for concurrent programming. Rust's concurrency model ensures safety by preventing data races and other concurrency pitfalls through its type system and ownership rules.

## Seventeenth
In this tutorial, we'll delve deeper into Rust's concurrency model by exploring the **message-passing** paradigm, particularly with **channels**. This concept allows threads to communicate safely without shared state, reducing the chances of race conditions.

**Channels**
Channels provide a mechanism for multiple threads to communicate by sending messages. Rust’s standard library provides a `channel` function that creates a new channel.

Let's dive in:

Create a new Rust file named `message_passing_channels.rs` and write the following code:

```rust
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
// Create a simple channel
let (tx, rx) = mpsc::channel();

// Spawn a new thread
thread::spawn(move || {
let values = vec![
String::from("Hello"),
String::from("from"),
String::from("the"),
String::from("spawned"),
String::from("thread!"),
];

for value in values {
tx.send(value).unwrap();
thread::sleep(Duration::from_millis(600));
}
});

// Receive messages in the main thread
for received in rx {
println!("Received: {}", received);
}
}
```

Key Points:

- **mpsc::channel**: This function creates a new channel and returns two ends: the transmitter (`tx`) and the receiver (`rx`).

- **tx.send(value)**: The spawned thread sends a series of messages via the transmitter.

- **rx**: The receiver acts as an iterator. In the main thread, we loop through messages received from the channel until it's closed.

- **move Closure**: We use the `move` keyword to move the ownership of values into the closure. Here, it ensures the transmitter end (`tx`) of the channel is owned by the spawned thread.

Compile and run the program. You'll see messages sent from the spawned thread and received in the main thread in the order they were sent, illustrating the concept of message passing between threads.

After this tutorial, you should understand how channels in Rust provide a safe and efficient mechanism for threads to communicate, encapsulating the complexities of concurrent programming and making it more approachable and less error-prone.

## Eighteenth
In this tutorial, we'll explore the concept of **Smart Pointers** in Rust. Smart pointers are data structures that not only act like pointers but also have additional metadata and capabilities. One of the most commonly used smart pointers in Rust is `Box`.

**Box**
A `Box` allows you to store data on the heap rather than the stack. What makes it "smart" is that it automatically cleans up the heap memory when the Box goes out of scope.

Let's dive into the basics of `Box`:

Create a new Rust file named `smart_pointers_box.rs` and write the following code:

```rust
// Define a simple recursive data structure using Box
enum List {
Cons(i32, Box),
End,
}

use List::{Cons, End};

fn main() {
// Using the Box to create a recursive data structure
let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(End))))));

// Function to compute the sum of the list
fn sum_list(l: &List) -> i32 {
match l {
Cons(value, next) => value + sum_list(next),
End => 0,
}
}

println!("Sum of list is: {}", sum_list(&list));
}
```

Key Points:

- **List Enum**: The `List` enum is a recursive data structure, where each element (`Cons`) holds an integer and a box that points to the next element. The last element is `End`.

- **Box::new**: This creates a new box and places the data on the heap. In this case, we use it to allocate each `Cons` variant on the heap.

- **sum_list Function**: This function recursively computes the sum of all elements in the list.

Compile and run the program. It will compute and display the sum of the elements in the list.

After this tutorial, you should understand the basic usage of the `Box` smart pointer in Rust. It allows for heap allocation and is especially useful for building recursive data structures due to its deterministic cleanup of heap memory when the data goes out of scope.

## Nineteenth
In this tutorial, we'll delve deeper into smart pointers and explore another important one: **`Rc`** (Reference Counted). While `Box` ensures data on the heap is cleaned up when it's no longer needed, `Rc` allows data on the heap to be shared among multiple parts of your program.

**Rc**
The "Rc" stands for "Reference Counting". This smart pointer tracks the number of references to a value which determines whether or not a value is still in use. If there are zero references to a value, the value can be cleaned up without any references becoming invalid.

Let's explore the use of `Rc`:

Create a new Rust file named `smart_pointers_rc.rs` and write the following code:

```rust
use std::rc::Rc;

#[derive(Debug)]
struct Data {
value: i32,
}

fn main() {
let data = Rc::new(Data { value: 42 });

println!("Reference count after creating data: {}", Rc::strong_count(&data));

{
let reference1 = Rc::clone(&data);
let reference2 = Rc::clone(&data);

println!("Reference count after creating two references: {}", Rc::strong_count(&data));

// Accessing data through one of the references
println!("Data value from reference1: {:?}", reference1);
}

println!("Reference count after inner scope ends: {}", Rc::strong_count(&data));
}
```

Key Points:

- **Rc::new**: This wraps the `Data` struct in an `Rc` smart pointer.

- **Rc::clone**: This does not deep-copy the data. Instead, it increments the reference count.

- **Rc::strong_count**: This returns the current reference count, allowing us to track how many references to a value currently exist.

Compile and run the program. You'll notice the reference count changes as you create and drop references to the `Rc`.

After this tutorial, you should understand how `Rc` in Rust provides a way to share heap-allocated data safely among multiple parts of your program. It ensures that the data remains alive as long as there's at least one reference to it and cleans up the data when the reference count drops to zero.

## Twenties
In this tutorial, we'll explore another crucial smart pointer: **`RefCell`**. While Rust's borrowing rules enforce at compile time that you either have multiple immutable references or a single mutable reference, `RefCell` allows you to bypass these rules and enforce borrowing rules at runtime.

**RefCell**
This smart pointer represents single ownership over the data it holds, but it allows mutable borrowing checked at runtime.

Let's understand how to use `RefCell`:

Create a new Rust file named `smart_pointers_refcell.rs` and write the following code:

```rust
use std::cell::RefCell;
use std::rc::Rc;

#[derive(Debug)]
struct Data {
value: RefCell,
siblings: RefCell>>,
}

fn main() {
let data = Rc::new(Data {
value: RefCell::new(42),
siblings: RefCell::new(Vec::new()),
});

let sibling1 = Rc::new(Data {
value: RefCell::new(10),
siblings: RefCell::new(Vec::new()),
});

let sibling2 = Rc::new(Data {
value: RefCell::new(20),
siblings: RefCell::new(Vec::new()),
});

data.siblings.borrow_mut().push(Rc::clone(&sibling1));
data.siblings.borrow_mut().push(Rc::clone(&sibling2));

// Modifying value inside RefCell
*data.value.borrow_mut() += 10;

println!("Updated data value: {:?}", data.value);
println!("Data siblings: {:?}", data.siblings.borrow().len());
}
```

Key Points:

- **RefCell::new**: Wraps data within a `RefCell`, giving the ability to have multiple mutable references to this data at runtime.

- **borrow_mut()**: Provides a mutable reference to the inner data if no other mutable references currently exist. This is checked at runtime.

- **siblings.borrow()**: Provides an immutable reference to the inner data.

Compile and run the program. You'll see that `RefCell` allows you to modify data even if there are multiple references to it, as long as only one mutable reference exists at a time.

## Twenty first
In this tutorial, we'll delve into Rust's pattern matching mechanism by discussing **`match`** expressions and **destructuring**.

**`match` Expressions**
Rust's `match` expression is a powerful tool for pattern matching, which lets you compare a value against a series of patterns and then execute code based on the first pattern that matches.

Let's explore pattern matching:

Create a new Rust file named `pattern_matching.rs` and write the following code:

```rust
enum WebEvent {
PageLoad,
PageUnload,
KeyPress(char),
Click { x: i64, y: i64 },
}

fn web_event_handler(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("Page loaded!"),
WebEvent::PageUnload => println!("Page unloaded!"),
WebEvent::KeyPress(c) => println!("Key '{}' pressed!", c),
WebEvent::Click { x, y } => println!("Clicked at x={}, y={}", x, y),
}
}

fn main() {
let pressed = WebEvent::KeyPress('x');
let clicked = WebEvent::Click { x: 20, y: 80 };

web_event_handler(pressed);
web_event_handler(clicked);
}
```

Key Points:

- **WebEvent Enum**: This enum represents various web events we might be interested in.

- **match expression**: The `match` expression checks the provided value (in this case, an instance of `WebEvent`) against all the given patterns and executes the associated code for the first match.

- **Destructuring**: In the patterns `WebEvent::KeyPress(c)` and `WebEvent::Click { x, y }`, we're destructuring the enum variants to get the inner values, which we then use in the code associated with the pattern.

Compile and run the program. You'll see that the appropriate messages get printed based on the events processed by the `web_event_handler` function.

After this tutorial, you should understand how the `match` expression provides a concise way to handle various patterns in Rust. It's a powerful tool for control flow and lets you handle different possibilities in a clear and readable manner.

## Twenty second
In this tutorial, we'll explore **Closures** in Rust. Closures are anonymous functions you can save in a variable or pass as arguments to other functions.

**Closures**
A closure captures values from the environment in which it's defined. They have the ability to capture values from their surrounding scope and can be short and expressive.

Let's delve into closures:

Create a new Rust file named `closures.rs` and write the following code:

```rust
fn main() {
// Simple closure with no parameters
let greet = || {
println!("Hello, Rust!");
};

greet();

// Closure with parameters
let add = |x, y| {
x + y
};

let result = add(5, 7);
println!("5 + 7 = {}", result);

// Closure that captures environment variables
let factor = 3;
let multiply = |x| x * factor;

println!("10 times factor = {}", multiply(10));
}

```

Key Points:

- **Closure Syntax**: Closures are defined using a pair of vertical bars `||`, followed by a block of code. This block of code can capture variables from the surrounding environment.

- **Environment Capture**: The `multiply` closure captures the `factor` variable from its surrounding environment.

Compile and run the program. You'll notice the different ways closures can be used in Rust, from simple no-argument closures to ones that capture environment variables.

## Advanced
## First
Let's explore some lesser-known, advanced Rust techniques and optimizations:

1. **Zero-Cost Abstractions**: Rust promises that abstractions won't have a runtime cost.

For instance, you can use iterators and higher-order functions like `map` and `filter` without fearing performance degradation.

```rust
let sum: u32 = (0..1000).filter(|&x| x % 2 == 0).sum();
```

The above code is as fast as the traditional loop but more expressive.

2. **Inlining**: Rust's `#[inline]` attribute hints the compiler to inline a function, which can improve performance.

```rust
#[inline]
fn add(a: i32, b: i32) -> i32 {
a + b
}
```

3. **Custom Allocators**: By default, Rust uses the system allocator, but you can specify custom allocators to optimize memory usage patterns for specific use-cases.

4. **Const Functions and `const fn`**: These allow computation at compile-time. It's a way of getting more done during compilation and less during runtime.

```rust
const fn compute_val() -> usize {
// Some compile-time computation
5 * 5
}

const VAL: usize = compute_val();
```

5. **Use of `unsafe`**: While the goal is to avoid using `unsafe` in Rust, sometimes, for performance reasons, it can be justified. This allows for optimizations that can't be done safely in pure Rust.

6. **Custom Derive and Procedural Macros**: You can generate custom implementations for your code. This allows for powerful metaprogramming techniques. For instance, the `serde` crate uses this to generate serialization/deserialization code for custom structs.

7. **Pattern Matching Optimizations**: Rust's `match` is optimized. A common trick is to match against literals which can be optimized into a jump table at compile-time.

8. **Lazy Static**: If you want to initialize something only once and use it across multiple calls or threads, `lazy_static` crate can be used:

```rust
lazy_static! {
static ref RE: Regex = Regex::new("...").unwrap();
}
```

9. **Optimizing Builds**: Using `lto` (Link Time Optimizations) and codegen units, you can further optimize binary sizes and performance.

```toml
[profile.release]
lto = true
codegen-units = 1
```

10. **Using `jemalloc`**: By default, Rust uses the system allocator. However, for certain workloads, using the `jemalloc` allocator might improve performance.

These are just some advanced techniques in Rust. As with all optimizations, it's essential to measure performance improvements with real-world data and understand the trade-offs being made.

## Second
We'll delve into the standard library's offerings for concurrency and parallelism, providing more detailed explanations and advanced examples.

## Rust's Standard Concurrency Mechanisms:

### 1. **Threads**

The most fundamental unit of execution in most operating systems is a thread. In Rust, you spawn a new thread using `std::thread::spawn`.

**Usage**: You should use raw threads for CPU-bound tasks or when you need a longer-lived, isolated piece of computation.

**Advanced Example**:
```rust
use std::thread;
use std::time::Duration;

fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
println!("Thread says {}", i);
thread::sleep(Duration::from_millis(1));
}
});

for i in 1..5 {
println!("Main thread says {}", i);
thread::sleep(Duration::from_millis(2));
}

handle.join().unwrap();
}
```

### 2. **Mutex (Mutual Exclusion)**

A `Mutex` ensures that only one thread can access some data at any given time. The type name `Mutex` stands for "mutual exclusion".

**Usage**: Use a mutex to protect shared data from concurrent modification.

**Advanced Example**:
```rust
use std::sync::Mutex;
use std::thread;

fn main() {
let counter = Mutex::new(0);
let mut handles = vec![];

for _ in 0..10 {
let handle = thread::spawn({
let counter = &counter; // Make a reference to the Mutex
move || {
let mut num = counter.lock().unwrap();
*num += 1;
}
});
handles.push(handle);
}

for handle in handles {
handle.join().unwrap();
}

println!("Result: {}", *counter.lock().unwrap());
}
```

### 3. **Rc (Reference Counting) and Arc (Atomic Reference Counting)**

`Rc` and `Arc` are reference-counted pointers. While `Rc` is for use in single-threaded scenarios, `Arc` is for multi-threaded situations.

**Usage**: Use `Arc` when you need multiple owners of the data, and the data can be accessed from multiple threads.

**Advanced Example**:
```rust
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
*num += 1;
});
handles.push(handle);
}

for handle in handles {
handle.join().unwrap();
}

println!("Result: {}", *counter.lock().unwrap());
}
```

### 4. **Channels**

Channels are a powerful feature in Rust to send data between threads.

**Usage**: Use channels for message-passing concurrency where you want to send data from one thread to another.

**Advanced Example**:
```rust
use std::sync::mpsc;
use std::thread;

fn main() {
let (tx, rx) = mpsc::channel();
let tx1 = mpsc::Sender::clone(&tx);

thread::spawn(move || {
let vals = vec![
"hi",
"from",
"the",
"thread",
];

for val in vals {
tx1.send(val).unwrap();
thread::sleep(Duration::from_secs(1));
}
});

for received in rx {
println!("Got: {}", received);
}
}
```

### 5. **Barriers**

A barrier is a thread synchronization primitive. Barriers allow multiple threads to synchronize the beginning of some computation.

**Usage**: Use when you want to ensure all threads have reached a certain point before any continue.

**Advanced Example**:
```rust
use std::sync::{Barrier, Arc};
use std::thread;

fn main() {
let iterations = 10;

let barrier = Arc::new(Barrier::new(iterations));
let mut handles = Vec::with_capacity(iterations);

for _ in 0..iterations {
let barrier_clone = barrier.clone();
handles.push(thread::spawn(move || {
println!("Before wait");
barrier_clone.wait();
println!("After wait");
}));
}

for handle in handles {
handle.join().unwrap();
}
}
```