Variáveis e Mutabilidade em Rust

Neste post, vamos explorar como variáveis, mutabilidade, constantes e shadowing funcionam na linguagem de programação Rust.

Por padrão, variáveis em Rust são imutáveis, ou seja, depois que um valor é atribuído, ele não pode ser alterado. Isso ajuda a evitar erros difíceis de rastrear e facilita o raciocínio sobre o código.

Exemplo (imutável):

fn main() {
    let y = 10;
    println!("O valor de y é: {y}");
    // y = 20; // Erro: não é possível alterar uma variável imutável
}

Se for necessário alterar o valor, basta adicionar a palavra-chave mut, tornando a variável mutável.

Exemplo (mutável):

fn main() {
    let mut y = 10;
    println!("O valor inicial de y é: {y}");
    y = 20;
    println!("Agora o valor de y é: {y}");
}

Mutabilidade deixa claro que o valor pode mudar, tornando o código mais legível para quem o mantiver no futuro.


Constantes

As constantes também são imutáveis, mas diferem das variáveis em alguns pontos:

  • São sempre imutáveis (não existe mut const).
  • Precisam ter tipo explícito.
  • Só podem receber valores conhecidos em tempo de compilação.
  • Podem ser declaradas em qualquer escopo, até o global.

Exemplo:

const MAX_SCORE: u32 = 1000;
const SECONDS_IN_DAY: u32 = 60 * 60 * 24;

fn main() {
    println!("A pontuação máxima é {MAX_SCORE}");
    println!("Um dia tem {SECONDS_IN_DAY} segundos");
}

Usar constantes evita “números mágicos” no código e facilita futuras alterações.


Shadowing (Sombreamento)

shadowing permite redefinir uma variável com o mesmo nome, criando uma nova variável (com let) que substitui temporariamente a anterior no escopo.

Exemplo:

fn main() {
    let z = 8;
    let z = z + 2; // z agora vale 10

    {
        let z = z * 3; // novo z no escopo interno
        println!("z dentro do escopo interno: {z}"); // 30
    }

    println!("z fora do escopo interno: {z}"); // 10
}

A vantagem é que o tipo da variável pode mudar, algo impossível com mut.

Exemplo (mudança de tipo):

fn main() {
    let input = "123";
    let input = input.parse::<i32>().unwrap(); // muda de &str para i32
    println!("O valor numérico é {input}");
}

Se tentássemos isso com mut, o compilador daria erro, pois uma variável mutável não pode mudar de tipo.