Lição 1: Estado explícito e invariantes

Antes de falar de memória, precisamos falar de estado. Um serviço de autenticação, um carrinho de compras ou um worker só é previsível quando sabemos quais valores podem mudar e quais precisam sempre existir.

Objetivo

Em uma frase: distinguir binding imutável, estado mutável e ausência representada por Option<T>.

Código dentro da main

Vamos evoluir um programa dentro da main, como faríamos num projeto real. Começamos com estado explícito: valores que não mudam ficam imutáveis; contadores e acumuladores declaram mutabilidade.

import io

func main(): int {
    let usuario: str = "mahua"
    let saldo: int = 340
    let contaAtiva: bool = true

    io.println(usuario)
    io.println(saldo)
    io.println(contaAtiva)
    return 0
}

main é a função de entrada do programa. O corpo entre { e } contém as instruções executadas em ordem; return 0 devolve o status de término ao sistema operacional.

Variáveis são imutáveis por padrão. Para mudar um valor, use mut:

let mut tentativas: int = 0
tentativas += 1
Dica

Se o valor não precisa mudar, deixe-o imutável. Menos estados para o leitor (e para o compilador) rastrear.

Experimente

Tire o mut de tentativas e veja o que o compilador diz. Ele vai te avisar — em tom de parceiro — que você está tentando reatribuir um valor imutável.

Garantia

Sem null, a categoria “aqui não tem nada” não fica escondida no tipo. Ou um valor existe, ou você usa Option<T> explicitamente. Essa distinção vira parte do contrato da função e pode ser tratada antes de chegar ao caminho de execução que precisa do valor.

Esse é o primeiro pilar: estado explícito e invariantes visíveis desde o início. Na próxima lição, vamos transformar regras de negócio em funções com contratos verificáveis.