Rust Pogramming Language
Variables
Declaration
Constants
Shadowing
Destructuring
struct Ponit2D(u32,u32);
let origin=Point2D(100,200);
let Point2D(x,y)=origin;
println("{:?} {:?}", x, y);
Data Types
Scalar Types
- Intergers
- characters
- boolean
- float
Integers
Signed integers have both +
and -
Unsigned integers are always positive;
Characters
Represents letters, specified using the char keyword
Use single quotes;
Compound Types
- Arrays
Arrays
- Fixed length
- Length known at compile time
- Heterogeneous - Can only contain items of the same data type
Accessing
- Access items by index
Tuples
- Fixed length
- length known at compile time
- Homogeneous - Items can be of different types
Empty tuple is known as
unit
Functions
- Arguments types are always required
- Return type alwasy required if value returned
- if not return type is unit (an empty tuple)
Structs
- A type composed of other types
- Can contain different types
Examples of structs
Access using the dot notation
Classic
- Ecah field has a name and type
let car1= Car{
make: String::from("Ford"),
model: String::from("Mustange"),
year: 1967,
}
println!(car1.year);
Tuple
- Similar to classic structs
- Fields have no names
struct Ponit2D(u32,u32);
let origin=Point2D(100,200);
println!("The value is {:?} and {:?}", origin.0, origin.1);
let Point2D(x,y)=origin;
println("{:?} {:?}", x, y);
Unit
- Have no fields
- Similar to the () unit type
Enum
- List all variations of some data
- Referred to as algebraic data types
enum CardialPoints {
North,
South,
East,
West
}
enum CardialPoints {
North(String),
South(String),
East(String),
West(String),
}
fn main(){
let north=CardialPoints::North;
let west=CardialPoints::West(String::from("West"));
}
- An Enum variant can include any kind of data
- Can have a variety of types
- Similar to structs with more flexibility
Advantages
- Describe what kind of data to be strored
- Each variant can be of different kind
- All variants stored under the same enum type
Expressions
Match
- A pattern matching
- A
scrutinee
expression is provided to the patterns - Arms are evaluated and compared with the scrutinee expression
fn main(){
let x = 1;
match x {
1 => println!(),
2 => println!("two"),
3 => println!("three")
_ => println!("something else"),
}
}
- The scrutinee expression is
x
- Each arm has a pattern and some code. the
=>
operator separates the pattern and the code to run - The first arm with a matching pattern is chosen as the branch target of the match
fn main() {
let x = 1;
let y = match x {
1 => 4,
2 => x,
_ => 5,
};
println!("The value is {}", y);
}
if else
Loops
loop
- Used to execute a code of block forever or until it's stopped or the program quits
break
can be used to stop a loop
while
- Conditional loops
- Run until a condition is met or become false
for
- Iterate over elements in a collection
- Each pass of the loop exreacts values
example 2
fn main() {
let mut i = 1;
let something = loop {
i *= 2;
if i > 100 {
break i;
}
};
println!("The value of something is {}", something);
for item in 0..5 {
println!("Value us {}", item);
}
}
Error Handling
Panic
- The Simplest way to handle error
- Quits the program execution
- Call the
panic!
macro along with the message to print out - Shoulb be used only if the program is in a unrecoverable state
Steps after a panic
- Failure message is printed
- Program unwinds and cleans up the stack
- Program quits
The Option enum
- Manages the existence of nonexistent values
- Type
T
is generic and associated with Some variant None
indicates no elemnt was foundSome
means that an element of typeT
was found
The Result enum
- Used for recoverable errors that are more common
- The
Ok(T)
variant represents success and contains a value - The
Err(E)
variant represnts an error - Used when a failure is expred
Mostly used for the following
- Parsing Strings
- File access
- Data Validation
Has the unwrap
and Expect
helper methods
Unwrap
returns the value T
of Ok(T)
variant and a panic
! for the Err
variant
Expect
returns a value just like unwrap
or called the panic!
macro with a detailed message
fn main(){
File::open("hello.txt").unwrap();
File::open("heloo1.txt").expect("Failed to open file");
}
The ?
operator
- Similar to match statement
For result Type
- Unwraps the value if OK variant
- Returns an error for Err variant
For Option Type
- Returns a value for Some variant
- Returns nothing for the None variant
Ownership
Rules of Ownership
- Each value in rust has a variable that is called it's
owner
. -
There can only be one owner at a time, to prevents
-
Dangling Pointers - pointers that do not point to a valid object of the appropriate type, for example if the memory is deallocated
- Double Free - Trying to free memory that has already been freed
- Memory Leaks - Not freeing memory that should have been freed
Rules of Ownership in functions
- Passing a variable to a function transfers the ownershop to that function
Borrowing
Options include cloning
fn main(){
let say = String::from("Hello");
print_out(say.clone());
println!(say)
}
fn print_out(out:String){
println!(out);
}
We borrow a variable by adding an &
to it
fn main(){
let say = String::from("Hello");
print_out(&say);
println!(say)
}
fn print_out(out: &String){
println!(out);
}
Mutable Borrowing
fn main(){
let mut myvec= vec![1,2,3];
println!("{:?}", myvec) //1,2,3
add_to_vec(&myvec);
println!("{:?}",myvec) //1,2,3,4
}
fn add_to_vec(a_vec: &mut Vec<i32>){
a_vec.push(4);
}
Read More on
- Enums
- &String vs &str *