| Length | Signed | Unsigned |
|---|---|---|
| 8-bit | i8 |
u8 |
| 16-bit | i16 |
u16 |
| 32-bit | i32 |
u32 |
| 64-bit | i64 |
u64 |
| 128-bit | i128 |
u128 |
| arch | isize |
usize |
Signed variants can store numbers from -(2n - 1) to 2n - 1 - 1 inclusive
i8: -(27) to 27 - 1, which equals -128 to 127.u8: 0- 2n - 1, that is 0 to 28 - 1, which equals 0 to 255Rust uses two’s complement wrapping to handle integer overflow silently. However, it offers explicit ways to manage overflow:
wrapping_* methods: Always wrap values (e.g., wrapping_add).checked_* methods: Return None if overflow occurs.overflowing_* methods: Return the result along with a boolean indicating overflow.saturating_* methods: Clamp the result to the type’s minimum or maximum value.Types: f32 and f64 (primitive types)
f32: single-precision floatf64: double precision floatBoolean: bool
Character: char 1
char type is four bytes in size and represents a Unicode Scalar Value.Group values of different types:
Fixed-length collections of the same type:
Short-hand:
value of elements; then number of elementsYou can access elements of an array using indexing:
x[0])Variables in Rust are immutable by default:
Use the mut keyword to make variables mutable:
Declared with const and are always immutable:
Shadowing allows reusing a variable name:
mut and Shadowingmut |
shadowing | |
|---|---|---|
| Type | Same type | Can change type (use of let) |
Use of let |
When first declared | All instances of variable use |
Functions can accept parameters/arguments:
Return the last expression from the function body:
if Expressionsfn main() {
let number = 3;
if number < 5 {
println!("Condition is true");
} else {
println!("Condition is false");
}
}if with a Boolean as its condition.else if for Multiple Conditionsfn main() {
let number = 6;
if number % 4 == 0 {
println!("Divisible by 4");
} else if number % 3 == 0 {
println!("Divisible by 3");
} else {
println!("Not divisible by 4 or 3");
}
}true condition, and once it finds one, it doesn’t even check the rest.if in a let Statementif is an expression, hence we can use it on the RHS of a let statement to assign the outcome to a variable
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}number variable will be bound to a value based on the outcome of the if expressionif must be the same typefn main() {
let condition = true;
let number = if condition { 5 } else { "six" };
println!("The value of number is: {number}");
}This throws an error because the types of the values in the if and else blocks are different.
looploopfn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("Result: {result}");
}break or return is never executed.break expression and a return expression as having the value unit, or ().while LoopWhile a condition evaluates to true, the code runs; otherwise, it exits the loop.
for Loopfor are the most commonly used loop construct in Rust.
loop Labels to DisambiguateLabeling loops when we have loops inside loops 1
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
}The break 'counting_up; statement will exit the outer loop.
wrapping_* methods: Always wrap values (e.g., wrapping_add).checked_* methods: Return None if overflow occurs.overflowing_* methods: Return the result along with a boolean indicating overflow.saturating_* methods: Clamp the result to the type’s minimum or maximum value.| Feature | Rust | R | Python | C/C++ |
|---|---|---|---|---|
| Arrays | Fixed-size, homogeneous types, defined as [T; N]. |
Homogeneous data, multidimensional (using array()). |
Homogeneous data, implemented via NumPy (numpy.array). |
Fixed-size, homogeneous, defined as T array[N]. |
| Vectors | A growable collection with Vec<T>. |
1D array, typically with c() or vector(). |
Lists mimic vectors, but for true vector operations, use NumPy arrays. | No native vector, use std::vector from the Standard Library (C++). |
| Tuples | Fixed-length, immutable collection: (i32, f64). |
Not commonly used, lists behave like tuples. | Immutable, ordered sequence: (1, 2, "text"). |
Use std::tuple (C++17+) or structures. |
| Matrices | Not native; use nested Vec<Vec<T>> or external libraries like nalgebra. |
2D structure (matrix()). Can extend to 3D with array(). |
Implemented with NumPy as 2D arrays: numpy.matrix or numpy.array. |
2D arrays as T matrix[rows][cols] or use libraries like Eigen in C++. |
| Mutability | Vectors (Vec<T>) are mutable; tuples are immutable. |
Vectors are mutable; matrices can be altered in-place. | Lists and arrays are mutable; tuples are immutable. | Arrays and vectors (std::vector) are mutable. Tuples are immutable in C++17+. |
| Indexing | 0-based indexing (e.g., x[0]). |
1-based indexing (e.g., x[1]). |
0-based indexing (e.g., x[0]). |
0-based indexing (e.g., x[0]). |
| Size Flexibility | Arrays are fixed, vectors grow dynamically. | Vectors and lists are dynamic. Arrays and matrices have fixed sizes. | Lists and NumPy arrays are dynamic; tuples are fixed size. | Arrays are fixed; std::vector is dynamic. |
A contiguous mutable array type, written as Vec<T>, short for ‘vector’.
Temperature Conversion:
Write a function to convert temperatures between Fahrenheit and Celsius.
Fibonacci Sequence:
Generate the nth Fibonacci number using recursion.
Christmas Carol:
Print the lyrics to “The Twelve Days of Christmas” with loops to reduce repetition.