Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

🦀 Tip of the day 08: No Free Lunches, No Free Defaults

In most languages, you can declare a variable and use it without ever giving it a value. What happens next depends on the language, and none of the options are great.

In C++, an uninitialized int contains whatever garbage was sitting in memory. Your program compiles, runs, and produces different results each time. This is undefined behavior; the compiler is not required to warn you, and debuggers will not always catch it.

In Python, you get a NameError at runtime. Maybe better than garbage 🤔? But you only find out when that exact line of code executes. If it is behind a rare if branch, it might not blow up until production.

In Rust, nothing has a default value unless you explicitly ask for one. If you try to use a variable before assigning it, the compiler rejects your code.

#![allow(unused)]
fn main() {
let x: i32;
println!("{}", x); // ERROR: used binding `x` isn't initialized
}

This is not a runtime crash. This is a compile-time error. Your program will not build until every variable has a value before it is used. Every code path, every branch, is checked before your code ever runs.

Late initialization is fine, as long as every path sets the value:

#![allow(unused)]
fn main() {
let temperature;

if sensor_available {
    temperature = read_sensor();
} else {
    temperature = 0; // Explicit fallback, your choice
}

println!("Temp: {}", temperature); // Works, both branches set it
}

The compiler tracks every possible code path. If even one branch leaves the variable unset, it will not compile.

What if I actually want a default?

Rust has the Default trait. But you have to opt in. Nothing gets it for free.

#![allow(unused)]
fn main() {
let x: i32 = Default::default();  // 0, but you asked for it explicitly
let s: String = Default::default(); // "", same idea
}

The key difference: in Rust, you wrote Default::default(), so anyone reading the code knows the default was intentional, not an accident.

The takeaway: Rust does not assume you want zero, false, or empty. If a value matters enough to exist, it matters enough to be set on purpose.

🔇 C++ lets you read uninitialized memory and calls it “performance.” Python waits until your code is running in production to tell you a variable does not exist. Rust just says no at compile time. Boring, but you sleep better.