To install Rust, copy and paste this to your terminal curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
After running this command, you need to add Rust env to your $HOME using :
source "$HOME/.cargo/env"
To write your first project, you will use the command line tool that comes with your installation - Cargo
cargo new app-name => Creates a new project called app-name .
That will automatically create a folder app-name, and bootstrap the following files
Src - main.rs
cargo.toml
Inside main.rs , you will have this code
fn main(){
println(“Hello , World”);
}
If you want to add a dependencies from the remote dependency registry known as crate , use :
cargo add dependency-name
If you want to check that your code is correct before running or building it, use :
cargo check
To run your code, use :
cargo run
To build your code, use :
cargo build
cargo update
will update existing dependencies
Learning Rust-> Lesson 2 : Basic Language Construct
Variables in Rust are immutable meaning the values in them cannot be change or reassigned a different value. If you want to have a mutable variable then you must define it as mutable
But
Constant must always be annotated with the right type. They are always immutable
OWNERSHIP AND BORROWING
Ownership is Rust’s most unique feature and has deep implications for the rest of the language. It enables Rust to make memory safety guarantees without needing a garbage collector.
Ownership is a set of rules that govern how a Rust program manages memory. All Programs have to manage the way they use a computer’s memory while running. Some languages have garbage collection that regularly looks for no-longer-used-memory as the program runs; in other languages, the programmer must explicitly allocate and free the memory.
Rust uses a third approach : Memory is managed through a system of ownership with a set of rules that the compiler checks.
If any of the rules are violated, the program won’t compile .
Both the stack and the heap are parts of the memory available to use by your program at runtime , but they are structured in different ways.
All data stored on the stack must have a known, fixed size. Data with unknown size or whose size might change must be stored on the heap
The heap is less organised, when you store data in the heap, the memory allocator must find a spot large enough to hold the data and then return a pointer as a reference to that location
The pointer to the heap can be stored on the stack since it is known and has a a finite size
When you want the actual data in the heap you must follow the pointer
Data to function calls are pushed onto the stack, after the function completes its execution they are popped off
Ownership Rules in Rust
The String type is a great example to learn how Rust manages memory
When a variable goes out of scope , Rust calls a special function known as drop to remove it from the
Every scalar type implements copy, No data that needs the heap can implement copy trait.
The return value for a function can be used for passing ownership to a variable
References and Borrowing
A reference is like a pointer in that it is an address that we can follow to access data stored at that address; that data is owned by some other variable .
Unlike a pointer, a reference is guaranteed to point to a valid value of a particular type for the life of that reference.
We call the action of creating a reference borrowing. As in real life, if a person owns something, you can borrow it from them. When you’re done, you have to give it back. You don’t own it.
Attempt to modify what we are referencing we throw an error because we do not own the data .
If we want to be able to mutate our references , we will use the mut. Keyword
Mutable references have one big restriction: if you have a mutable reference to a value, you can have no other references to that value
The Rules of References
Let’s recap what we’ve discussed about references:
String Slices
A string slice is a reference to part of a String, and it looks like this:
ENUMS AND PATTERN MATCHING
Enum IPAddress = {
V4 ,
V6,
}
In Rust, there is a match construct that you can use to compare against a list of values and then execute code based on the matching.
Matches in Rust are exhaustive. They must cover all edge cases
Packages and Crates
A Package can contain multiple binary crates and optionally one library crate. As a package grows, you can extract parts into separate crates that become external dependencies
A crate is the smallest amount of code that the rust compiler considers at a time. Crates can contain modules, and the modules may be defined in other files that get compiled with the crate.
A crate can come in one of two forms : Binary Crate or a Library Crate.
Binary Crates are programs you can compile to an executable that you can run, such as a command line program or a server.
Each must have a function called main that defines what happens when the executable runs.
Library crates don’t have a main function, and they don’t compile to an executable. Instead, they define functionality intended to be shared with multiple projects.
Rustaceans refer to library when they say crate
A package is a bundle of one or more crates that provides a set of functionality . A package contains a cargo.toml file that describes how to build those creates.
If you are creating any package, the src/main.rs is the root of a binary package while src/lib.rs is the root of a library package
A package can have multiple binary crates by placing files in the src/bin directory ; each file will be a separate binary crate
Error Handling
In Rust, we talk about two kinds of errors : Recoverable and Unrecoverable errors
Recoverable error are those kind of errors that your program can recover from . An example is trying to read the content of a file that does not currently exist
An unrecoverable error is a serious error for example trying to accessed the index of an array that is out of bound. This will cause your program to panic
We can use the following construct for handling recoverable errors :
Expresson.unwrap()
expression.expect(‘Your message’)
Match expression {
Ok(value) => Do whatever you want to do with it,
Err(err) => Do whatever you want to do with the error ,
}
For unrecoverable errors while doing testing , debugging or whatsoever, you can use :
Panic!(“Your error message”)