Skip to content

Latest commit

 

History

History
741 lines (595 loc) · 11.6 KB

RUST.md

File metadata and controls

741 lines (595 loc) · 11.6 KB

Rust Programming Language Tutorial

Table of Contents

  1. Introduction to Rust
  2. Installation
  3. Hello, World!
  4. Variables and Constants
  5. Data Types
  6. Functions
  7. Control Flow
  8. Ownership
  9. References and Borrowing
  10. Slices
  11. Structs
  12. Enums
  13. Pattern Matching
  14. Modules and Packages
  15. Collections
  16. Error Handling
  17. Generics
  18. Traits
  19. Lifetimes
  20. Smart Pointers
  21. Concurrency
  22. Macros
  23. Crates and Cargo
  24. Testing
  25. Documentation
  26. Best Practices

Introduction to Rust

Rust is a systems programming language focused on safety, speed, and concurrency. It achieves memory safety without a garbage collector and is designed to be both fast and safe.


Installation

To install Rust, use rustup, the Rust toolchain installer:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

After installation, you can update Rust with:

rustup update

Hello, World!

Create a new Rust project using Cargo:

cargo new hello_world
cd hello_world

Edit src/main.rs:

fn main() {
    println!("Hello, world!");
}

Run the program:

cargo run

Variables and Constants

Variables

fn main() {
    let mut x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

Constants

const MAX_POINTS: u32 = 100_000;

Data Types

Scalar Types

  • Integer
  • Floating-point
  • Boolean
  • Character

Compound Types

  • Tuple
  • Array

Examples

fn main() {
    let x: i32 = 42;
    let y: f64 = 3.14;
    let is_active: bool = true;
    let character: char = 'A';

    let tuple: (i32, f64, u8) = (500, 6.4, 1);
    let array: [i32; 3] = [1, 2, 3];
}

Functions

Definition

fn main() {
    another_function();
}

fn another_function() {
    println!("Another function.");
}

Parameters

fn main() {
    print_value(5);
}

fn print_value(x: i32) {
    println!("The value is: {}", x);
}

Return Values

fn main() {
    let x = five();
    println!("The value of x is: {}", x);
}

fn five() -> i32 {
    5
}

Control Flow

If Statements

fn main() {
    let number = 6;

    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }
}

Loops

  • loop
  • while
  • for

Examples

fn main() {
    let mut counter = 0;

    let result = loop {
        counter += 1;
        if counter == 10 {
            break counter * 2;
        }
    };

    println!("The result is {}", result);

    let mut number = 3;

    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }

    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        println!("the value is: {}", element);
    }
}

Ownership

Ownership Rules

  1. Each value in Rust has a variable that’s called its owner.
  2. There can only be one owner at a time.
  3. When the owner goes out of scope, the value will be dropped.

Example

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;
    // println!("{}", s1); // This will cause an error
}

References and Borrowing

References

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);
    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

Mutable References

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
}

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

Slices

Slices let you reference a contiguous sequence of elements in a collection rather than the whole collection.

String Slices

fn main() {
    let s = String::from("hello world");
    let hello = &s[0..5];
    let world = &s[6..11];
    println!("{} {}", hello, world);
}

Array Slices

fn main() {
    let a = [1, 2, 3, 4, 5];
    let slice = &a[1..3];
    println!("{:?}", slice);
}

Structs

Definition

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool,
}

Instantiation

fn main() {
    let user1 = User {
        email: String::from("[email protected]"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
}

Methods

impl User {
    fn full_name(&self) -> String {
        format!("{} <{}>", self.username, self.email)
    }
}

fn main() {
    let user1 = User {
        email: String::from("[email protected]"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    println!("{}", user1.full_name());
}

Enums

Definition

enum IpAddrKind {
    V4,
    V6,
}

Instantiation

fn main() {
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
}

Enums with Data

enum IpAddr {
    V4(String),
    V6(String),
}

fn main() {
    let home = IpAddr::V4(String::from("127.0.0.1"));
    let loopback = IpAddr::V6(String::from("::1"));
}

Pattern Matching

match Keyword

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn value_in_cents(coin: Coin) -> u32 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

if let

fn main() {
    let some_value = Some(3);
    if let Some(3) = some_value {
        println!("Three");
    }
}

Modules and Packages

Modules

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

fn main() {
    crate::front_of_house::hosting::add_to_waitlist();
}

Packages and Crates

Packages are a collection of crates. A crate can be a binary or a library.


Collections

Vectors

fn main() {
    let v: Vec<i32> = Vec::new();
    let v = vec![1, 2, 3];
}

Strings

fn main() {
    let mut s = String::from("foo");
    s.push_str("bar");
}

Hash Maps

use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
}

Error Handling

Result

use std::fs

::File;
use std::io::ErrorKind;

fn main() {
    let f = File::open("hello.txt");

    let _f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => panic!("Problem opening the file: {:?}", other_error),
        },
    };
}

panic!

fn main() {
    panic!("crash and burn");
}

Generics

Definition

fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

Traits

Definition

pub trait Summary {
    fn summarize(&self) -> String;
}

Implementation

pub struct Article {
    pub headline: String,
    pub content: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        format!("{}, {}", self.headline, self.content)
    }
}

Default Implementation

pub trait Summary {
    fn summarize(&self) -> String {
        String::from("(Read more...)")
    }
}

Lifetimes

Basic Lifetime Annotation

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Structs with Lifetimes

struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt { part: first_sentence };
}

Smart Pointers

Box

fn main() {
    let b = Box::new(5);
    println!("b = {}", b);
}

Rc

use std::rc::Rc;

fn main() {
    let a = Rc::new(5);
    let b = Rc::clone(&a);
    println!("a = {}, b = {}", a, b);
}

RefCell

use std::cell::RefCell;

fn main() {
    let x = RefCell::new(5);
    *x.borrow_mut() += 1;
    println!("x = {:?}", x);
}

Concurrency

Threads

use std::thread;
use std::time::Duration;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..10 {
            println!("hi number {} from the spawned thread!", i);
            thread::sleep(Duration::from_millis(1));
        }
    });

    for i in 1..5 {
        println!("hi number {} from the main thread!", i);
        thread::sleep(Duration::from_millis(1));
    }

    handle.join().unwrap();
}

Channels

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

Macros

Declarative Macros

macro_rules! say_hello {
    () => {
        println!("Hello!");
    };
}

fn main() {
    say_hello!();
}

Procedural Macros

Procedural macros are more complex and typically used for code generation.


Crates and Cargo

Creating a New Crate

cargo new my_crate

Building and Running

cargo build
cargo run

Adding Dependencies

Add dependencies in Cargo.toml:

[dependencies]
serde = "1.0"

Testing

Writing Tests

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

Running Tests

cargo test

Documentation

Writing Documentation

Use /// for documentation comments:

/// Adds one to the given number.
///
/// # Examples
///
/// ```
/// let five = 5;
/// assert_eq!(6, add_one(five));
/// ```
fn add_one(x: i32) -> i32 {
    x + 1
}

Generating Documentation

cargo doc --open

Best Practices

Tips

  1. Write Idiomatic Rust: Follow Rust conventions and idioms.
  2. Use rustfmt: Automatically format your code.
  3. Use clippy: Catch common mistakes and improve your Rust code.
  4. Document Your Code: Write clear and concise documentation.
  5. Test Thoroughly: Write tests for all critical code paths.
  6. Handle Errors Gracefully: Use Result and Option effectively.
  7. Keep Dependencies Updated: Regularly update and audit dependencies.
  8. Learn from the Community: Engage with the Rust community for best practices and support.

This tutorial provides a comprehensive overview of Rust, from basic concepts to advanced techniques. By mastering these topics, you'll be able to write safe, concurrent, and efficient Rust programs.

Here is a link to a Youtube Tutorial which can help you learn the language in a better way <>

https://youtu.be/BpPEoZW5IiY?si=jPOCC5yanWbrFIAL