What a constant is
A constant is a named value that can never change. Rust variables are already immutable by default, so what makes const different? A constant is fixed at compile time and can never be made mutable. A plain let variable could later be rewritten as let mut by someone editing the code, but a const can't. When a value is a fact of your program, such as a mathematical constant or a limit, const says so in the code itself.
Declaring a constant
You write the keyword const, then the name, then a colon and the type, then = and the value:
const OUR_NAME: &str = "AlgoCademy";
println!("{}", OUR_NAME); // Output: AlgoCademy
Two details differ from a let variable:
- The type is required. A constant never relies on inference.
const LIMIT = 5;is rejected withmissing type for `const` item, and the compiler suggests: i32. - The name is written in SCREAMING_SNAKE_CASE. That means capital letters with underscores between words, like
MAX_SPEED. A lowercase constant still compiles, but the compiler warns that itshould have an upper case name.
A constant can't be reassigned
The whole point is that nobody can change it. Assigning to a constant is an error:
const PI: f64 = 3.14;
PI = 5.0;
println!("{}", PI);
The compiler stops with error[E0070]: invalid left-hand side of assignment, pointing at PI with the note cannot assign to this expression. Nothing runs. Adding mut doesn't help either: const mut X: i32 = 1; fails with const globals cannot be mutable.
A constant must have a value
A constant can't be declared first and filled in later. const OUR_NAME: &str; is rejected with free constant item without body, and the compiler suggests providing a definition with = <expr>;.
The value also has to be computable while the program is being compiled. Plain literals and arithmetic on other constants are fine:
const SECONDS_PER_DAY: u32 = 60 * 60 * 24;
println!("{}", SECONDS_PER_DAY); // Output: 86400
Calling an ordinary function is not, so const NAME: String = String::from("x"); fails with cannot call non-const associated function. Use a &str constant for text.
Why use constants
For a tiny program, they don't matter much. In a large project with many authors, they act as a guarantee. Picture the core values that describe a company:
const COMPANY_NAME: &str = "Apple";
const FOUNDING_DATE: &str = "April 1st, 1976";
const FOUNDER_NAME: &str = "Steve Jobs";
Years later, when hundreds of people work on the code, a careless COMPANY_NAME = "Other"; in some distant file won't compile. The mistake is caught immediately, rather than turning up as a wrong value in production.
Constants also remove "magic numbers". A line like if retries > 3 makes the reader wonder what 3 means, and the same number may be repeated in many places. A named constant, MAX_RETRIES, is described once and changed in one place.
A let variable can't borrow the name of a constant either. After const PI: f64 = 3.14;, a line such as let mut PI = 2.0; fails with let bindings cannot shadow constants. This closes another back door: the name keeps its meaning everywhere it is visible.
const against let
let | const | |
|---|---|---|
| Can be made changeable | yes, with mut | never |
| Type annotation | optional | required |
| Value known at compile time | not needed | required |
| Can be declared outside any function | no | yes |
| Naming style | snake_case | SCREAMING_SNAKE_CASE |
A constant declared at the top of a file, outside every function, is visible to all the code in that file. Constants can also be declared inside a function, as the exercises do.
Solving the exercise
The starting code declares PI and then tries to change it:
const PI: f64 = 3.14;
PI = 5.0;
println!("{}", PI);
This can't compile, because of the assignment. The task is to make the program print 3.14, and the way to do that is to delete the assignment line. Keep the declaration and the println! as they are:
const PI: f64 = 3.14;
println!("{}", PI);
The program prints 3.14. The blank lines left behind are harmless.
Key takeaways
const NAME: Type = value;declares a value that never changes.- The type is always required, and the name is conventionally in capital letters.
- Assigning to a constant is a compile error, and
mutis not allowed on one. - A constant needs a value at compile time, so it can't call ordinary functions.
- Use constants for fixed facts and limits, and give them names instead of repeating raw numbers.
