Ben Chuanlong Du's Blog

It is never too late to learn.

Define Variables in Rust

In [3]:
:timing
:sccache 1
:dep once_cell = "1.13.0"
use once_cell::sync::Lazy;
Out[3]:
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.

In [20]:
let x = 1;
x
Out[20]:
1
In [21]:
x = 2
x = 2;
^^^^^ cannot assign twice to immutable variable
cannot assign twice to immutable variable `x`

let mut

In [19]:
let mut y = 2;
y = 3;
y
Out[19]:
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.

In [17]:
const my_const_var = 1;
const my_const_var = 1;
                   ^ expected `:`
expected `:`, found `=`
In [16]:
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.

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

Define a static variable.

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

Comments