Variable bindings, Constants & Statics

Variable bindings, Constants & Statics

⭐️ In Rust, variables are immutable by default, so we call them Variable bindings. To make them mutable, the mut keyword is used.

⭐️ Rust is a statically typed language; it checks data types at compile-time. But it doesn’t require you to actually type it when declaring variable bindings. In that case, the compiler checks the usage and sets a better data type for it. But for constants and statics, you must annotate the type. Types come after a colon(:).

💭 We use the data types like bool, i32, i64 and f64 in the following examples. But, no need to check them now, due to we discuss them later.

  • Variable bindings

The let keyword is used in binding expressions. We can bind a name to a value or a function. Also, because the left-hand side of a let expression is a “pattern”, you can bind multiple names to a set of values or function values.

let a; // Declaration; without data type
a = 5; // Assignment

let b: i8; // Declaration; with data type 
b = 5;

let t = true;        // Declaration + assignment; without data type
let f: bool = false; // Declaration + assignment; with data type

let (x, y) = (1, 2); // x = 1 and y = 2

let mut z = 5;
z = 6;

let z = { x + y }; // z = 3

let z = {
    let x = 1;
    let y = 2;

    x + y
}; // z = 3
  • Constants

The const keyword is used to define constants and after the assignment their values are not allowed to change. They live for the entire lifetime of a program but has no fixed address in the memory.

const N: i32 = 5;
  • Statics

The static keyword is used to define a “global variable” type facility. There is only one instance for each value, and it’s at a fixed location in memory.

static N: i32 = 5;

💭 While you need constants, aways use const, instead of static. It’s pretty rare that you actually want a memory location associated with your constant, and using a const allows for optimizations like constant propagation, not only in your crate but also in downstream crates.

Variable Shadowing

Sometimes, while dealing with data, initially we get them in one unit but need to transform them into another unit for further processing. In this situation, instead of using different variable names, Rust allows us to redeclare the same variable with a different data type and/ or with a different mutability setting. We call this Shadowing.

fn main() {
    let x: f64 = -20.48; // float
    let x: i64 = x.floor() as i64; // int
    println!("{}", x); // -21

    let s: &str = "hello"; // &str
    let s: String = s.to_uppercase(); // String
    println!("{}", s) // HELLO
}

Before going to the next…

  • The naming convention for the variable bindings is using the snake_case. But, for constants and statics, we should follow the SCREAMING_SNAKE_CASE.

  • Usually, constants and statics are placed at the top of the code file, outside the functions (after module imports/ use declarations).

const PI: f64 = 3.14159265359;

fn main() {
    println!("π value is {}", PI);
}