Basic Syntax and Variables in Rust
Rust is known for its emphasis on safety and performance, making it a great choice for both beginners and seasoned programmers alike. In this article, we will dive into the fundamental aspects of Rust syntax, exploring how to declare variables, understanding data types, and performing basic operations. Let’s get coding!
Variables in Rust
In Rust, variables are immutable by default, meaning once a variable is assigned a value, it cannot be changed. This leads to safer code as it prevents accidental changes to data. However, you can make variables mutable by using the mut keyword.
Declaring Variables
You declare a variable using the let keyword followed by the variable name. For example:
#![allow(unused)] fn main() { let x = 5; }
In this case, x is an immutable variable holding the value of 5. Trying to modify x later in the code will result in a compile-time error:
#![allow(unused)] fn main() { x = 10; // This will cause a compile error }
To create a mutable variable, simply use mut like so:
#![allow(unused)] fn main() { let mut y = 10; y = 20; // This is perfectly fine because y is mutable }
Constants
In Rust, you can also declare constants using the const keyword. Constants are always immutable and must have a type annotation. They can be declared at any scope and are not limited to functions:
#![allow(unused)] fn main() { const MAX_POINTS: u32 = 100_000; }
Shadowing
Rust also supports a feature called shadowing, which allows you to reuse a variable name. Shadowing creates a new variable that shadows the previous one, allowing you to change the type of the variable if needed:
#![allow(unused)] fn main() { let z = 10; let z = z + 5; // Now, z is 15 }
Data Types in Rust
Rust is a statically typed language, meaning that the type of every variable must be known at compile time. Here are the most important data types:
Scalar Types
-
Integers: These can be signed (e.g.,
i32,i64) or unsigned (e.g.,u32,u64). The default type for integers isi32.#![allow(unused)] fn main() { let a: i32 = 42; let b: u64 = 1000; } -
Floating-point Numbers: Rust has two floating-point types,
f32andf64, withf64being the default.#![allow(unused)] fn main() { let pi: f64 = 3.14159; } -
Booleans: These represent truth values and can only be
trueorfalse.#![allow(unused)] fn main() { let is_rust_fun: bool = true; } -
Characters: In Rust, a
charis a single Unicode character and is represented using single quotes.#![allow(unused)] fn main() { let first_letter: char = 'R'; }
Compound Types
-
Tuples: A tuple is a fixed-size collection of different types. You can create a tuple like this:
#![allow(unused)] fn main() { let tuple: (i32, f64, char) = (500, 6.4, 'z'); // Accessing tuple elements let (x, y, z) = tuple; println!("x: {}, y: {}, z: {}", x, y, z); } -
Arrays: An array is a fixed-size collection of elements of the same type. To declare an array, you specify the type and size:
#![allow(unused)] fn main() { let arr: [i32; 5] = [1, 2, 3, 4, 5]; // Accessing array elements let first = arr[0]; println!("First element: {}", first); }
Simple Operations
With variables and data types in place, let's take a look at some simple operations you can perform in Rust.
Basic Arithmetic
Rust supports basic arithmetic operations such as addition, subtraction, multiplication, and division:
#![allow(unused)] fn main() { let a = 10; let b = 5; let sum = a + b; // Addition let difference = a - b; // Subtraction let product = a * b; // Multiplication let quotient = a / b; // Division let remainder = a % b; // Modulus println!("Sum: {}, Difference: {}, Product: {}, Quotient: {}, Remainder: {}", sum, difference, product, quotient, remainder); }
Control Flow: If and Else
You can control the flow of your program using conditionals. The if statement in Rust is quite intuitive:
#![allow(unused)] fn main() { let number = 10; if number < 0 { println!("Negative number"); } else if number == 0 { println!("Zero"); } else { println!("Positive number"); } }
Loops
Rust provides loop, while, and for loops to handle repetitive tasks.
Loop:
#![allow(unused)] fn main() { loop { println!("This will loop forever unless we break!"); break; // Exits the loop } }
While Loop:
#![allow(unused)] fn main() { let mut count = 0; while count < 5 { println!("Count: {}", count); count += 1; } }
For Loop:
#![allow(unused)] fn main() { let arr = [1, 2, 3, 4, 5]; for element in arr.iter() { println!("Element: {}", element); } }
Pattern Matching with match
Pattern matching is a powerful control flow construct in Rust. It allows you to branch logic based on the value of a variable or expression:
#![allow(unused)] fn main() { let number = 3; match number { 1 => println!("One"), 2 => println!("Two"), 3 => println!("Three"), _ => println!("Not one, two, or three"), } }
Conclusion
As you can see, Rust's basic syntax is clear and expressive, providing a robust framework for writing safe and efficient code. Understanding the variables, data types, and operations lays the groundwork for more advanced concepts in Rust. Keep practicing and exploring the possibilities they offer!
In our next article, we’ll take a deeper dive into functions and how they work in Rust, so stay tuned!