Rust Tutorial – Part 3 – Constants

[This post is part of the series on Rust programming tutorials that I’m writing for enjoyment. All the tutorial links are here.]

Rust allows you to write constants; that is, things that aren’t going to change at all. If you’ve read the previous tutorial on variables, you might be thinking: why constants when all variables are immutable by default? Good question. And just in case you weren’t thinking like that, begin to. It’s one of the best things you can do for your programming career.

The first very important distinction is that constants can exist in global scope. In other words, this means that is you have a fixed value that needs to shared throughout your Rust application (read ‘many files’), plain old variables won’t cut the mustard.

let y = 10;

fn main() {
    println!("y is {}", y);
}

Something like the above fails to compile. Rust complains that it wasn’t expecting a let┬ástatement up there. This means that variables must have a block scope (another fancy way of saying that they must live inside curly braces) and cannot be shared among files.

A constant, however, can:

const AGE: u8 = 10;

fn main() {
    println!("Age is {}", AGE);
}

The above works. But did you notice that odd little u8 there? This stands for ‘unsigned 8 bits’, and happens to be the size and type of the constant we are declaring (here’s how it helps; and if you’re totally clueless about integer sizes, I’d suggest reading up some computer architecture . . . something like this).

Anyway, back to the point. If you now have a Rust project with multiple files, the AGE constant will be available to all of them, and will last as long as the program lasts.

Another, less important, distinction is that constants cannot be re-initialized (the following will throw an error):

const AGE: u8 = 10;
const AGE: u8 = 12;

fn main() {
    println!("Age is {}", AGE);
}

While variables can be:

fn main() {
    let x = 12;
    println!("x is {}", x);    
    let x = 23;
    println!("x is {}", x);
}

A curious aside, by the way. Rust compiler will warn you bitterly if you create variables you won’t use. I originally wrote the following program for the previous code:

fn main() {
    let x = 12; 
    let x = 23;
    println!("x is {}", x);
}

But when I compiled it, Rust said:

core$ rustc 01_variables_and_mutation.rs 
warning: unused variable: `x`
 --> 01_variables_and_mutation.rs:2:9
  |
2 |     let x = 12;
  |         ^
  |
  = note: #[warn(unused_variables)] on by default
  = note: to avoid this warning, consider using `_x` instead

Kinda neat, right?

At this point, I have a question nagging me, which I’m going to post on Rust forums: If the compiler can figure out the type of the variable from a let statement, why can’t it do so from a const statement? Why are we required to specify the type and size of storage when declaring a constant?

(Update: Shortly after, I did take this discussion to the Rust forums.)

[The link to the next post is here.]

Leave a Reply

Your email address will not be published. Required fields are marked *