Date created: 01/01/2025 By: Gabriel Baje
- Rust is a systems programming language that focuses on performance, memory safety, and safe concurrency.
- Memory Safety without Garbage Collection
- Ownership, Borrowing, and Lifetimes
- Zero-Cost Abstractions
- Concurrency and Parrallelism
- Trait System and Pattern Matching
- Pattern Matching
- Functional and imperative paradigms
- Crates and Package Management
- No Null or Undefined Behaviour
- Cross-Platform Compatibility
- Ecosystem and Community
- Compiled Language
cargo: the Rust package manager.rustc: the Rust compiler is sometimes invoked by cargo since your code is also treated as a package.rustdoc: the Rust documentation tool for documenting comments in Rust code.
- The important parts of a Rust project are seen when we use Cargo to initialize a new project. eg:
cargo new examplecargo.toml: stores metadata for the package..gitignore: stores files that Git should not track.src/main.rs: Thesrc/subdirectory is where all Rust code is normally written. Themain.rsfile is the entry point for all binary crates.
- Rust's
mainfunction can behave like every other function by accepting and returning values. - Comments for the documentation are made with the double forward slash:
//. - The
->symbol is how you specify return values. eg(main function):
fn main() -> () {
let x = 5;
println!("The value of x is {}", x);
}mutkeyword stands for mutable when creating a variable. This allows a variable to be reassigned without initializing it.
- Integer types
- Floating-point types
- Machine-dependent integer types
Under Textual types, you should find characters char and str. They are created like this:
fn main() -> (){
let single_alphabet = "a";
println!('The single chracter is: {}', single_alphabet);
let second_alphabet: char = 'b';
println!("The single character with type inference is {}", second_alphabet);
} fn main() -> (){
let my_string = "hello world";
println!("The string is : {}", my_string);
let second_string: &str = "Hello, other world";
println!("The string contnt with the type reference is: {}", second_string);
}Notice the ampersand (&) we used during the type inferred variable second_string.
Non-complicated way to create strings in Rust is to use automatic dynamically sized String keyword:
fn main() -> (){
let another_string = String::from("Hello, world");
println!("The string is: {}", another_string);
let new_string: String = String::from("Hey, world!");
println!("The type inferred string content is: {}", new_string);
}-
In Rust, sequential typesrefer to data structures that store a sequence of values in a specific order.
-
Arrays
//Declaration and initialization of an array
let numbers: [i32, 5] = [1, 2, 3, 4, 5];- Slices Slices are references to a contiguous sequence of elements within another sequential type (like an array or a vector).
let numbers = [1, 2, 3, 4, 5];
let slice: &[i32] = &numbers[1..4];- Vectors
Vectors are dynamic arrays that can grow or shrink in size.
// Creating and modifying a vector
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
vec.push(3);- Strings
Rust's
Stringtype is dynamically sized, UTF-8 encoded string.
let mut text = String::from("Hello, ");
text.push_str("world!");- Ranges Ranges are sequential types reoresenting a sequence of values from a start value to an end value.
for number in 1..5 { // Inclusive range (1 to 5 inclusive )
println!("Current number: {}", number);
}- Tuples
Tuples are collections of values of different types, and they have a fixed size that's determined at compile time.
// Creating tuples
let person: (String, i32, bool) = ("Alice".to_string(), 30, true);
// Accessing tuple elements
let name = person.0; // Access the first element (name)
let age = person.1; // Access the second element (age)
let is_adult = person.2;// Access the third element (is_adult) fn greet(){
println!("Hello, world!");
} fn say_hello(name: &str){
println!("Hello, {}!", name);
}- Here, the
say_hellofunction takes a single argument of type&str(a string slice) and prints personalized greeting using that argument.
fn square(n: i32) -> i32 {
n*n
}- In the above example, the
squarefunction takes ani32argument and returns the square of that argument as ani32.
fn calculate_power(base: f64, exponent:i32) -> f64{
if exponent == 0{
1.0
}else{
let mut result = base;
for _ in 1..exponent.abs(){
result*= base;
}
if exponent < 0{
1.0 / result
}else{
result
}
}
}The calculate_power function takes a base of type f64 and an exponent of type i32.