Data Types
Note: Rust is a statically typed language. This means that the type of a variable must be known at compile time. This is in contrast to dynamically typed languages like Python, where the type of a variable is determined at runtime.
bool: A boolean value that can be either true or false
let is_true: bool = true;
char: A single Unicode character.
let c: char = 'a';
i8,i16,i32,i64,i128: Signed integers with different sizes
let x: i32 = -69;
u8,u16,u32,u64,u128: Unsigned integers with different sizes
let x: u32 = 420;
f32,f64: Floating-point numbers with different precisions.
let x: f32 = 69.420;
- ‘array’: A fixed-size array of elements of the same type.
let a: [i32; 3] = [1, 2, 3];
Vec: A growable array of elements of the same type.
let v: Vec<i32> = vec![1, 2, 3];
usize,isize: The pointer-sized unsigned and signed integers.
let x: usize = 420;
tuple: An ordered collection of elements of different types
let t: (i32, f32, char) = (69, 420.69, 'a');
&str: A string slice that points to a valid UTF-8 string stored elsewhere.
let s: &str = "Hello World";
String: A heap-allocated string, growable at runtime.
let s: String = String::from("Hello World");
Variables
- Declaring a variable with the
letkeyword
let x = 69;
- Variables are immutable by default, but you can make them mutable with the
mutkeyword.
let mut x = 69;
x = 420;
- You can also declare multiple variables with the same type.
let (x, y, z): (i32, i32, i32) = (1, 2, 3);
- Rust has block-scoped variables. This means that variables declared inside a block are only accessible inside that block.
let x = 42;
{
let x = 43;
println!("{}", x); // prints 43
let y = 69;
}
println!("{}", x); // prints 42
println!("{}", y); // error: y is not in scope
- You can also declare constants with the
constkeyword. Constants are always immutable and must be annotated with their type. Constants can be declared in any scope, including the global scope.
const PI: f32 = 3.14159265359;
Shadowing
- You can declare a variable with the same name as a previous variable, and the new variable shadows the previous variable.
let x = 69;
let x = 420;
- You can also change the type of a variable when you shadow it.
let x = 69;
let x = "Hello World";
Control Flow
ifstatements can be used to branch on a condition
let x = 42;
if x == 42 {
println!("The answer is {}", x);
} else {
println!("The answer is not {}", x);
}
ifstatements can also be used as expressions
let x = if true { 69 } else { 420 };
loopstatements can be used to create infinite loops
let mut i = 0;
loop {
print!("{} ", i);
i += 1;
if i == 10 {
break;
}
}
whilestatements can be used to repeat a block of code while a condition is true
let mut i = 0;
loop {
println!("{}", i);
i += 1;
if i == 10 {
break;
}
}
forstatements can be used to iterate over a collection
for i in 0..10 {
println!("{}", i);
}
let a = [1, 2, 3];
for i in 0..a.len() {
println!("{}", a[i]);
}
for i in &a {
println!("{}", i);
}
for i in a.iter() {
println!("{}", i);
}
// Reverse iteration
for i in (0..10).rev() {
println!("{}", i);
}
for i in (0..10).step_by(2) {
println!("{}", i);
}
// Filtered iteration
// Equivalent to: for i in 0..10 { if i % 2 == 0 { println!("{}", i); } }
// Note: filter() is a method on the Iterator trait
// Explanation: Only even numbers are passed to the closure, which is then passed to the filter() method
for i in (0..10).filter(|x| x % 2 == 0) {
println!("{}", i);
}
matchstatements can be used to match a value against a pattern
let x = 42;
match x {
0 => println!("Zero"),
1 => println!("One"),
_ => println!("Something else"),
}
Output: Something else
matchstatements can also be used as expressions
let x = match 42 {
0 => "Zero",
1 => "One",
_ => "Something else",
};
println!("{}", x);
Output: Something else
if letstatements can be used to match a value against a pattern and bind the value to a variable
let x = Some(42);
if let Some(i) = x {
println!("{}", i);
} else {
println!("No value");
}
Output: 42
Functions
- Declaring a function with the
fnkeyword
fn add(x: i32, y: i32) -> i32 {
x + y
}
Note: The
-> i32part of the function signature is the return type. If the function doesn’t return a value, the return type is written as-> ().
- Rust has expressions and statements, and functions can return expressions.
// This function returns an expression
fn add(x: i32, y: i32) -> i32 {
x + y
}
// This function returns a statement
fn print(x: i32) {
println!("{}", x);
}
- You can also declare functions inside other functions.
fn main() {
fn add(x: i32, y: i32) -> i32 {
x + y
}
}