Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

:timing
:sccache 1
:dep once_cell = "1.13.0"
use once_cell::sync::Lazy;
sccache: true

let

  1. By default, let defines an immutble variable. To define a mutable variable, you have to use let mut.

  2. let can only be used in a function, which means that you cannot define a variable using let in a module. const and static can be used in any scope.

let x = 1;
x
1
x = 2
x = 2;
^^^^^ cannot assign twice to immutable variable
cannot assign twice to immutable variable `x`

let mut

let mut y = 2;
y = 3;
y
3

const and static Variables

  1. You must specify the type of a variable explicitly when defining it using the const or static keyword.

  2. Below summarizes the difference between let and const.

    • mut is NOT allowed with const since a const can never be changed.

    • const requires explit types while let support type inference.

    • A const variable is resolved and inlined at compile time which means that a const variable must be a constant expression which can be determined at compile time. It cannot be the result of a function call or anything that could only be determined at runtime.

  3. Below summarizes the differences between static and const.

    • Both const and static can be considered as defining constant values. const is the traditional compile-time concept as in C++ (different from final in Java which is not a compile-time concept). static defines a static lifetime variable. A variable defined using static is usually used as immutable (and thus can be treated as a constant). Accessing or modifiying a mutable static variable can only done through unsafe code.

    • Both const and static requires explicit types.

    • A const variable is inlined into the code at compile time, which means that it is not a good choice for defining large data. Defining large data as a static variable is a better alternative.

    • Currently, you can associate a const variable with a struct but you cannot associate a static variable with a struct. However, this might change in future as there is a Pre-RFC: Associated statics proposing supporting associated statics.

    • You probably do not really need const ...

    For more discussions, please refer to Const vs static .

const

You must specify a type when defining a const variable, o.w., the code won’t compile.

const my_const_var = 1;
const my_const_var = 1;
                   ^ expected `:`
expected `:`, found `=`
const my_const_var: i32 = 1;

static

When defining a static variable which implements Copy, you can define it as a static reference. This helps avoiding accidental implicity copies. A more idiomatic way is to define a wrapper non-Copy struct so that you can be sure that the underlying data won’t get copied.

An example where a static array is copied implicitly.
static ARR: [usize; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let a = [ARR, ARR, ARR];

Define a static variable.

mod abc {
    pub static x: i8 = 1;
}
abc::x
1
static GLOBAL_VEC: Lazy<Vec<i32>> = Lazy::new(|| {
    let mut v = Vec::new();
    v.push(1);
    v.push(10);
    v.push(20);
    v
});
fn print_vec(v: &[i32]) {
    v.iter().for_each(|i| {
        println!("{i}");
    });
}
print_vec(&GLOBAL_VEC)
1
10
20
()
static GLOBAL_ARR: Lazy<[i32; 3]> = Lazy::new(|| {
    [100, 200, 300]
});
fn print_arr(v: &[i32]) {
    v.iter().for_each(|i| {
        println!("{i}");
    });
}
let arr: &[i32; 3] = &GLOBAL_ARR;
print_arr(arr)
100
200
300
()