Rust 1: Curl - Proto ' HTTPS' - Tlsv1.2 - SSF HTTPS://SH - Rustup.Rs - SH Rustc - Version Cargo - Version
Rust 1: Curl - Proto ' HTTPS' - Tlsv1.2 - SSF HTTPS://SH - Rustup.Rs - SH Rustc - Version Cargo - Version
RUST
https://www.linkedin.com/learning/rust-essential-training/anatomy-of-a-rust-program?
autoSkip=true&autoplay=true&dApp=112132386&leis=LAA&resume=false&u=67551194
rustc —version
cargo —version
rustc main.rs
RUST 1
Dependencies
To include external libraries for dependency
Variables
variable in rust starts with let
fn main(){
let x = 10;
RUST 2
The variable must be explicitly declared as mute in order to change the value.
fn main(){
x = 20;
Note: As a convention snake case is followed for all the local variables in rust.
Rust is a statically typed language - every variable should be defined at compile time.
Ruts is also a strongly typed language - ( implicit ) dynamically changing data types of
the variables at runtime is not allowed.
Integers :
fn main(){
let x : u8 = 255;
x = x + 1;
println(” x is {} ”, x);
RUST 3
}
Rust catches these overflow at compile time itself in the latest versions.
Overflow at runtime will lead to panic and asserts the program from running.
Float :
Rust supports f32 & ( f64 as default).
let x = 22.0/7.0
Arithmetic Operations:
Rust support ( + - * / %)
Typecasting :
let x = 10;
let b = 3.0;
let c = a as f64/b;
eg : let x = 300;
BODMAS:
RUST 4
Formatting:
println!(" x is {}", c); → x is 2.33333333335
Bitwise :
Rust allows defining binary data.
NOT → x = !x;
OR . → x = x | 0b0000_1111;
XOR → x = x^0b0101_0101;
SHIFT → x = x<<2;
RUST 5
Boolean :
let x = true;
let y = false;
Comparison Operator:
== != <= >= > <
let x = ‘1’;
let x = ’\u{261D}’;
Array :
The array holds multiple values of the same data type in a consecutive memory
location.
fn main(){
println!(” first number {}”, numbers[0]); →compile error reading uninitialized array
println!(” first number {}”, numbers[5]); → compile time error index our of range
let n = 6;
RUST 6
println!(” first number {}”, numbers[n]); → run time panic
let array_len: usize = numbers.len(); → size of usize depends on platform(4 bytes 32bit)
let garage [[[i32; 100]; 20]; 5]; → 5 floors, 20 rows, 100 cars in each
Initializing an array
RUST 7
Initializing an array with variable is not allowed in rust
Tuple:
Tuple holds multiple values of multiple data types in consecutive memory locations.
fn main() {
stuff.0 += 1;
Functions :
Rust functions doesn't need declarations.
fn main(){
RUST 8
say_hello() ;
}
fn say_hello(){
say_number();
fn say_number(number: i32){
let x = 1;
let y = 2;
say_sum(x, y); → since we did not specify the data type of x, y, and say_sum is the first
function it encountered that takes x & y as parameters compiler assumes x & y as u8 .
say_number(x); → will throw a compile time error because compiler previously assumed
that x is u8
say_numer(x as i32);
Statement vs Expression:
The statement is an expression without a return value & ends with a semicolon.
An Expression will have a result & does not end with semicolon.
RUST 9
Return :
fn square(x: i8) -> u32 {
x * x
fn main(){
println!(” result {?}”, result); rust doesn't have a format specifier for tuple so we can
use a compiler format specifier ? to print a tuple
}
If the function doesn't return anything by default, the compiler assumes it returns a unit
value.
eg:
fn hello() → (){
RUST 10
Conditional Execution:
fn main () {
let x = 3;
if x == 3 {
let x = 3;
if true { → is valid
println!(” Condition is True”);
RUST 11
RUST 12
IF- ELSE in single line
fn main (){
fn main (){
let x = if condition {3} else {4.0}; → Compile error if and else have incompatible
types.
}
Loops :
loop → loop is basically infinite loop and need as break statement to exit the loop
RUST 13
We can make loop typically a statement and make it to return a value
while
RUST 14
for
Under the hood for loop converts the message array into an iterator, iterator has a
method next() this for loop use this next method internally and iterate through the
message array till the end.
if we are using older version of rust than 1.5 then we should use message.iter()
we can get index of the array by using array.iter().enumerate() this returns a tuple
with index and value
RUST 15
Iterate through loop for a range of values.
RUST 16
Nested Loops :
RUST 17
Variable Scope
In rust, variable bindings are constrained to live within a block of code.
{
fn main() {
let message = [1, 2, 3 ];
println!("{}", message); -> [1, 2, 3]
let message = "hello";
println!("{}", message); -> hello
}
fn main(){
let planet = "earth";
if true{
let planet = "mars";
println!("{}", planet); -> mars
}
println!("{}", planet); -> earth
}
String literal
Rust string data type is called string literal cause it's literally written in the code, the
compiler will hardcode the string into the executable.
When the program runs it gets loaded into the memory, when the program needs to use
the literal value it will access using the reference.
RUST 18
fn main(){
let message: String = String :: from("Earth"); -> string type
let planet: &str = "Earth"; -> string literal
}
fn main(){
let mut message = String :: from("Earth");
message.push_str("is home");
RUST 19
Ownership
Variables are responsible for freeing their own resources.
Rules
When the owning variable goes out of scope the value is dropped.
fn main(){
RUST 20
println!("{}", outer_planet);
}
fn main(){
RUST 21
Scenario if data is in Stack.
fn main(){
RUST 22
Transferring ownership
fn main(){
let rocket_fuel = 1;
process_fuel(rocket_fuel);
println!("{}", rocket_fuel);
}
fn process_fuel(propellant: i32){
println!("{}", propellant);
}
fn main(){
let rocket_fuel: String = String::from("RP-1");
process_fuel(rocket_fuel);
println!("{}", rocket_fuel); -> compilation error value is moved
}
fn process_fuel(propellant: String){
println!("{}", propellant);
}
RUST 23
fn main(){
let rocket_fuel: String = String::from("RP-1");
let rocket_fuel = process_fuel(rocket_fuel);
println!("{}", rocket_fuel);
}
fn main(){
let rocket_fuel: String = String::from("RP-1");
let rocket_fuel = process_fuel(rocket_fuel.clone());
println!("{}", rocket_fuel);
}
fn process_fuel(propellant: String){
println!("{}", propellant);
}
Borrowing References
fn main(){
let rocket_fuel: String = String::from("RP-1");
let length = process_fuel(&rocket_fuel); & -> borrow operator (reference)
println!("{} {}", rocket_fuel, length);
}
RUST 24
Borrowing mutable reference
fn main(){
let mut rocket_fuel: String = String::from("RP-1");
let length = process_fuel(&mut rocket_fuel);
println!("{} {}", rocket_fuel, length);
}
Note : while using a mutable reference, it's not allowed to create another reference in
that scope.
Even though the other references are nonmutable it's not allowed.
This is to prevent data races (every object should have only one owner at any instance).
RUST 25
Dangling reference
fn main(){
let fuel = process_fuel();
}
Returning a pointer to a local variable creates a dangling pointer, rust doesn't allow it.
Fix for the above problem instead of creating a dangling pointer pass the owner ship.
fn main(){
let fuel = process_fuel();
println!("{}", fuel)
}
RUST 26
Slices
In order to create references for sub set for an array/strings we use slices.
fn main(){
let messge = String::from(" Message from Earth! ");
let last_word: &str = &messge[14..14+5];
println!("{}", last_word);
}
fn main(){
let messge = String::from(" Message from Earth! ");
let last_word: &str = &messge[14..14+50]; -> compiles but panics at runtime
println!("{}", last_word);
}
fn main(){
let planets:i32 = [1, 2, 3, 4, 5, 6, 7, 8]
let inner_planets: &[i32] = &planets[..4];
println!("{:?}", inner_planets);
}
fn main(){
let message: String = String::from("Message from Earth !");
let first_word: &str = get_first_word(&message);
println!("{}", first_word);
}
RUST 27
}
}
return &message; //no space found return entire string
}
RUST 28
But String can act as str because str itself doesn't own any object its just a slice
(contains pointer and its length but not capacity ), but vice versa is not possible.
Trim Spaces
fn main(){
let message: String = String::from("Message from Earth !");
let no_spaces = trim_spaces(message.clone());
println!("{}", no_spaces);
Ruts come with a standard library std which is not a part of rust language but a
module.
We can import these modules from std using key word use . eg : use std::thread;
Stringis a part of std . but we don't need to import it with std every time we use is
because
it's a part of prelude , prelude only includes the most common modules used.
Standard input
use std::io;
RUST 29
fn main() {
let mut buffer = String::new();
println!("Enter message ");
io::stdin().read_line(&mut buffer);
println!("Input is {}", buffer);
}
Std input by default returns string (with a \n at the end), if we want to convert the input
and use it we need to parse it.
use std::io;
fn main() {
let mut buffer = String::new();
println!("Enter number :");
io::stdin().read_line(&mut buffer);
let number: i32 = buffer.trim().parse().unwrap();
println!("Input + 1 is {}", number+1);
}
Crate
In rust, the therm crate refers to the collection of rust source code files.
In order to use these crates in our program, we need to add them to cargo.toml file.
[dependencies]
rand = "0.8.5"
use rand;
fn main() {
RUST 30
let number = rand::random::<f64>();
println!("Random number is {}", number);
}
rand comes with its own prelude which includes the most common functions in rand.
use rand::prelude::*;
fn main() {
let number = random::<f64>();
println!("Random number is {}", number);
let n = thread_rng().gen_range(1..10);
println!("Thred Random number generator {}", n);
use rand;
use std;
fn main(){
let secretVal = rand::thread_rng().gen_range(1..50);
println!("--- START GAME ---");
loop{
RUST 31
}
println!("--- GAME END ---");
}
RUST 32