Learning-Rust
Rust is to be installed using official cargo distribution.
Rustlings course
TIP
Installed with
cargo install rustlingsand initialised withrustlings init
Intro
Lines are printed with println!() and the main function is defined as fn main().
fn main(){
println!("Hello World!");
}Variables
Variables are declared with let keyword and the type is defined with :. Mutable variables need to be defined with mut keyword. Same variable can be reused by changing its type.
fn main(){
let num = "THREE";
println!("The number is {num}");
let mut num:i32 = 10;
println!("The number is {num}");
num = 100;
println!("The number is {num}");
}Functions
fn call_me(num: i32) -> i32 {
return num*num;
}
fn main(){
let square = call_me(32);
println!("The square of 32 is {square}");
}If-Else
fn check_str(fruit: String) -> i32 {
if fruit == "apple" {
1
} else if fruit == "orange" {
2
} else {
3
}
}Vectors
Vectors are dynamic arrays. Similar to vector in C++, the vector is stored in the heap with a pointer in the stack. However, since vectors don’t have
the Copy trait, they are moved in cases where C++ or Python would shallow copy.
fn main() {
let mut v: Vec<i32> = vec![10, 20, 30, 40];
for i in 0..=10 {
v.push(i);
}
let mut v1 = Vec::<i32>::new();
v1.push(5);
let mut v2 = v;
v2.push(11);
}Mapping over Vectors
Vectors can be mapped using the iter() method and map() function.
fn double_element(vector: Vec<i32>) -> Vec<i32> {
vector
.iter()
.map(|v| v * 2)
.collect()
}Move semantics
Rust uses the system of borrowing and moving to manage memory. In this system, unless specified, the ownership of a variable is passed to any operation.
In cases where the operation has its own scope, such as passing a variable to a function, the variable is moved to the function scope so the function
will own the variable. To avoid this a reference to a variable a can be passed with &a and a reference b can be dereferenced with *b.
fn main() {
let s:String = String::from("Hello");
take_ownership(s);
let mut s1: String = give_ownership("Hello");
println!("Main received {}", s1);
let s2: String = take_and_give_ownership(&mut s1);
println!("Main received {}", s2);
}
fn take_ownership(s: String) {
println!("Took ownership of {}",s);
}
fn give_ownership(s: &str) -> String {
s.to_string()
}
fn take_and_give_ownership(s:&mut String) -> String {
s.push_str(", World!");
s.to_string()
}Multiple references
Every reference of a variable is kept in memory until the last time it is used, after which it is cleared. This memory management is decided at compile time. If a mutable reference to a variable exists, no other reference to the variable can exist. This is to prevent multiple sources of write to the variable which can cause data races. However, any number of immutable references can exist simultaneously as they cant overwrite the variable.
fn main() {
let mut num: i32 = 5;
let num1 = #
let num2 = # // Valid as existing ref is immutable
println!("{}, {}", num1, num2); // num1 and num2 cleared as they are never used again
let num3 = &mut num;
// let num4 = # // Using this would be invalid as existing ref num3 is mutable
println!("{}", num3); // num3 cleared as it is never used again
let num5 = &mut num; // Valid as num3 is never used again
*num5 += 1; // Writes to num5 which changes num
}