In Rust, constants are compile-time determined and immutable values used to define data that does not change in a program. Unlike variables, constants must have their type explicitly specified and can be declared in the global scope, making them ideal for configuration or mathematical constants.

Basic Syntax of Constants

Use the const keyword to declare a constant, with the syntax: const NAME: type = value;. Constant names are typically in uppercase letters with underscores for readability. The example below shows how to define a constant for pi.

const PI: f64 = 3.14159;
fn main() {
    println!("The value of pi is: {}", PI);
}
// Output: The value of pi is: 3.14159

Note: Constants must be evaluated at compile time, so values computed at runtime cannot be used.

Constant Expressions and Compile-Time Computation

Rust allows the use of constant expressions in constants, which are evaluated at compile time. For example, you can define values based on other constants or use simple arithmetic operations.

const TWO: i32 = 2;
const SQUARE: i32 = TWO * TWO; // Computed as 4 at compile time
fn main() {
    println!("The square of TWO is: {}", SQUARE);
}
// Output: The square of TWO is: 4

Using Constants to Improve Code Maintainability

Defining magic numbers or strings as constants can make code clearer and easier to maintain. For example, when configuring an application, use constants to define default values or limits.

const DEFAULT_TIMEOUT: u64 = 30;

fn process_request(timeout: u64) {
    if timeout > DEFAULT_TIMEOUT {
        println!("Request timeout");
    }
}
fn main() {
    process_request(20);
    // Output: (no output, because 20 <= 30)
}

In this way, if you need to change these values, you only need to modify the constant definition without searching through the entire codebase.

Scope and Visibility of Constants

Constants can be declared in modules or the global scope and are private by default. Use the pub keyword to make them public for use in other modules.

mod config {
    pub const API_KEY: &str = "secret-key";
    const INTERNAL_VALUE: i32 = 42; // Private constant
}
fn main() {
    println!("API key: {}", config::API_KEY);
    // println!("{}", config::INTERNAL_VALUE); // Error: private constant not accessible
}
// Output: API key: secret-key