Lesson 1: Explicit state and invariants

Before memory, we need to talk about state. An authentication service, shopping cart, or worker is easier to reason about when we know which values may change and which must remain valid.

Goal

In one sentence: distinguish immutable bindings, mutable state, and absence represented by Option<T>.

Code inside main

We will evolve one program inside main, as we would in a real project. We start with explicit state: values that do not change stay immutable; counters and accumulators declare mutability.

import io

func main(): int {
    let name: str = "mahua"
    let balance: int = 340
    let active: bool = true

    io.println(name)
    io.println(balance)
    io.println(active)
    return 0
}

main is the program entry point. The body between { and } contains instructions executed in order; return 0 sends the exit status back to the operating system.

Variables are immutable by default. To change a value, use mut:

let mut attempts: int = 0
attempts += 1
Tip

If a value does not need to change, keep it immutable. Fewer states for the reader (and the compiler) to track.

Try it

Remove the mut from attempts and see what the compiler says. It will warn you — in a partner-like tone — that you are trying to reassign an immutable value.

Guarantee

Without null, the category “there is nothing here” simply does not exist as a sneaky value. Either a value exists, or you use Option<...> explicitly. Nothing appears out of nowhere at runtime.

That is the first pillar: explicit state and visible invariants from the start. Next, we turn domain rules into functions with verifiable contracts.