← Back to Rust Course | Chapter 2: Variables & Types | Lesson 1 of 7

Declaring Variables with let

The word let is how you tell Rust "I want to remember this value under a name."
Syntax
rust
let name = value;
let name: Type = value;

Basic let Bindings

The let keyword creates a new variable binding, associating a name with a value. Once assigned, that value can be read anywhere later in the same scope.

Example: Basic let Bindings

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `language`, set to `"Rust"`
    let language = "Rust";
    // Print "Learning {}" to the console, substituting in `language` (with a trailing newline)
    println!("Learning {}", language);
}

Type Annotations

Although Rust can usually infer a variable's type from its value, you can add an explicit type annotation after a colon. This is required when the type cannot be inferred, and is sometimes used for clarity.

Example: Type Annotations

markup
// Entry point: execution of the program starts here
fn main() {
    // Declare an immutable variable `count` (an integer), set to `42`
    let count: i32 = 42;
    // Print "count = {}" to the console, substituting in `count` (with a trailing newline)
    println!("count = {}", count);
}

Immutability by Default

Variables created with let are immutable by default, meaning you cannot assign a new value to them after creation. Attempting to do so is a compile error, which is Rust's way of preventing accidental changes.

Note: Try uncommenting a reassignment line for an immutable variable locally -- the compiler error message is very descriptive.

Example: Immutability by Default

markup
fn main() {
    let pi = 3;
    println!("pi is approximately {}", pi);
    // pi = 4; // this line would fail to compile
}

Scope of Variables

A variable is only valid within the block of code (the curly braces) where it was declared. Once that block ends, the variable goes out of scope and can no longer be accessed.

Example: Scope of Variables

markup
// Entry point: execution of the program starts here
fn main() {
    {
        // Declare an immutable variable `inner`, set to `"only visible here"`
        let inner = "only visible here";
        // Print "{}" to the console, substituting in `inner` (with a trailing newline)
        println!("{}", inner);
    }
    // Print "Outer scope continues" to the console (with a trailing newline)
    println!("Outer scope continues");
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting that variables declared with plain let are immutable by default and cannot be reassigned.
  2. Trying to use a variable before it has been given a value with let.
  3. Assuming let always needs an explicit type, when Rust can usually infer it from the assigned value.
Chapter Summary
  • let binds a name to a value; by default the binding is immutable.
  • Rust infers types automatically in most cases, but you can annotate them explicitly with let x: i32 = 5;.
  • A variable must be initialized before it is used.
  • Bindings are scoped to the block { } they are declared in.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.