Basic Syntax of Rust

Basic Syntax of Rust

ยท

6 min read

Introduction

A warm welcome into the new year and as a developer who is always curious to learn new things and share knowledge no matter how little the knowledge can be, it's still learning

In this series guide, we're going through the basic syntax of rust and as we proceed in gaining more grasp and knowledge of how to use the language effectively, we get to build projects and play around with areas in which rust can be implemented.

At the end of this article, we will understand in detail types reference variables memory management ownership functions.

Let's jump onto this together. ๐Ÿš€

fn main() {
    println!("Hello rust!");
}

Above are the norms for every developer picking out any language, we all start with the hello world print out.

Variables

A variable is a piece of memory that has a name and a type, and which stores a value. We can think of a variable as a container that holds a value, and that we can access and manipulate in our program.

To declare a new variable in Rust, you use the let keyword followed by the name you want to give to the variable and the type of value it will hold.

let x: i32 = 5;

This creates a new variable named x of type i32 (a 32-bit integer) and assigns it the value 5.

Once you have declared a variable, you can access its value by using its name. For example, you could write x + 1 to add 1 to the value of x. You can also reassign a new value to a variable using the = operator.

let x: i32 = 5;
x = 6;

This changes the value of x from 5 to 6.

It's important to note that, in Rust, variables are immutable by default. This means that once you have assigned a value to a variable, you cannot change that value. To make a variable mutable, we need to use the mut keyword when declaring it.

let mut x: i32 = 5;
x = 6;

This creates a mutable variable x and allows you to change its value later in the program

Types

In general, there are what we call the scaler type and compound type in programming, and in rust, it makes no difference either. A scalar type is a data type that represents a single value. Scalar types include integers, floating-point numbers, and Boolean values. These types can be used to represent simple values such as numbers, true/false conditions, and characters.

Compound types, on the other hand, are data types that can contain multiple values. Examples of compound types include arrays, structs, and tuples. These types allow you to group multiple values together and manipulate them as a single entity.

Here's an example that shows the difference between a scalar type and a compound type in Rust:

fn main() {
    // Scalar types:
    let x: i32 = 5;
    let y: f32 = 3.14;
    let z: bool = true;

    // Compound types:
    let a: [i32; 3] = [1, 2, 3];
    let b: (i32, f32, bool) = (10, 0.5, false);
}

In this code, x, y, and z are scalar variables of type i32, f32, and bool, respectively. a is an array of i32 values with a fixed length of 3, and b is a tuple containing three values of different types: an i32, an f32, and a bool.

References

In Rust, a reference allows you to borrow value from one place in your code and use it in another place, without taking ownership of the value. This means you can use the value, but you don't have the right to modify it or move it to a different location in memory.

References are created using the & operator, also known as the "reference operator". For example, to create a reference to an i32 value, you can write &x, where x is an i32 variable.

There are two types of references in Rust: mutable and immutable. An immutable reference &T allows you to borrow a value, but it does not allow you to modify it. A mutable reference &mut T allows you to borrow a value and modify it.

fn main() {
    let x = 10;
    let y = 20;

    let ref_x = &x;  // Create an immutable reference to `x`.
    println!("ref_x: {}", ref_x);  // Print the value of `x` through the reference.

    let ref_y = &mut y;  // Create a mutable reference to `y`.
    *ref_y = 30;  // Modify the value of `y` through the reference.
    println!("y: {}", y);  // Print the modified value of `y`.
}

The output of this program would be:

ref_x: 10
y: 30

In this example, ref_x is an immutable reference to x, and ref_y is a mutable reference to y. The value of x can be accessed through ref_x, but it cannot be modified. The value of y can be both accessed and modified through ref_y.

Dangling Reference

A dangling reference in Rust is a reference that points to a value that has been deallocated (freed from memory). Dangling references can occur when a reference outlives the value it points to, or when a reference is used after the value it points to has been moved to a different location in memory.

Dangling references are a common cause of runtime errors because they can lead to undefined behavior or segmentation faults. To prevent these errors, Rust has a borrowing system that checks whether a reference is valid at runtime. If a reference is invalid, the Rust compiler will reject the code.

fn main() {
    let x = Box::new(10);  // Create a heap-allocated value and store it in `x`.
    let y = &x;  // Create a reference to the value in `x`.
    drop(x);  // Deallocate the value in `x`.
    println!("y: {}", y);  // Dangling reference!
}

Functions

A function is a block of code that performs a specific task and may or may not return a value.

fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

This function, called greet, takes a string slice as an argument and returns a String. The -> String syntax is called a function signature, and it specifies the types of the arguments and the return value.

To call a function, you simply use its name followed by a pair of parentheses, and pass any required arguments inside the parentheses.

let greeting = greet("Izzy");
println!("{}", greeting);

This would print Hello, Izzy! to the console.

Functions can also have multiple parameters and multiple return values, as well as have no parameters or return values at all.

fn add_and_multiply(x: i32, y: i32) -> (i32, i32) {
    (x + y, x * y)
}

This function takes two i32 values as arguments, and returns a tuple of two i32 values.

To a break and in some other series, we discuss more on it what we learned.