Tanto em JavaScript quanto em Rust, const, let e mut definem como variáveis se vinculam a valores e se esses valores podem ou não mudar. Elas podem parecer semelhantes, mas refletem objetivos de design e comportamentos de execução muito diferentes.

Antes de entrar em let e mut, vale esclarecer uma confusão comum: o const de Rust não tem nada a ver com o const de JavaScript. Apesar do mesmo nome, os dois conceitos resolvem problemas completamente distintos.

const em Rust vs. const em JavaScript

Em JavaScript, const impede a reatribuição, mas não torna o valor interno imutável. O binding é fixo — o dado não.

1const arr = [1, 2];
2arr.push(3); // ✅ permitido
3arr = [4, 5]; // ❌ TypeError

O nome da variável arr não pode ser reatribuído, mas o array pode ser modificado livremente. Isso pode causar problemas sutis em React, por exemplo:

1const [items, setItems] = useState([1, 2]);
2
3items.push(3); // ⚠️ permitido, mas altera o estado diretamente
4setItems(items); // React pode não detectar a mudança

O const de JavaScript é um binding em tempo de execução (runtime). A linguagem não impede que você modifique um valor que deveria permanecer constante.

Em Rust, const é algo totalmente diferente. Ele define uma constante de tempo de compilação (compile-time), um valor conhecido antes da execução e embutido diretamente no binário compilado — não armazenado na heap nem na stack.

1const PI: f64 = 3.1415;
2
3fn main() {
4    let r = 2.0;
5    let area = PI * r * r;
6    println!("Área: {}", area);
7}

O compilador substitui cada referência a PI por seu valor literal durante a compilação. Isso o torna ideal para dados que nunca mudam, como constantes matemáticas, limites fixos ou parâmetros de configuração. Se você precisar de um valor calculado em tempo de execução, deve usar let, que aloca memória (na stack ou na heap) e existe apenas durante a execução.

let em Rust vs. let e const em JavaScript

Com o const esclarecido, podemos comparar como as duas linguagens tratam vínculos e mutabilidade por meio de let.

Em JavaScript:

  • let permite reatribuir e modificar o valor.
  • const impede a reatribuição, mas ainda permite alterar o objeto ou array subjacente.

Em Rust:

  • let cria um binding imutável, e o valor também é imutável.
  • let mut permite tanto reatribuir quanto modificar internamente o valor.
1let v = vec![1, 2];
2// v.push(3); // ❌ não pode emprestar como mutável
3
4let mut v = vec![1, 2];
5v.push(3); // ✅ funciona

Neste ponto, let mut em Rust se comporta de forma semelhante ao let em JavaScript — ambos permitem mutação. A diferença é que Rust exige uma escolha explícita e opcional, enquanto JavaScript assume mutabilidade por padrão.

Vínculos e valores

Um binding conecta um nome a um valor, e o valor é o dado real armazenado na memória. A mutabilidade pode afetar qualquer um dos dois, dependendo da linguagem.

A regra de Rust é clara: você deve declarar exatamente onde a mudança é permitida, em vez de presumir isso em toda parte. Essa explicitude permite que o compilador garanta segurança contra data races e efeitos colaterais inesperados.

Em outras palavras, a filosofia de Rust é imutabilidade por padrão. É preciso optar explicitamente pela mutabilidade com mut, tornando cada alteração de estado intencional e visível ao compilador.

1let mut counter = 0;
2counter += 1;

Essa exigência aumenta a segurança, especialmente em código concorrente ou multithread. Ela também se estende a referências: é possível emprestar um valor de forma imutável (&) ou mutável (&mut), mas nunca ambas ao mesmo tempo.

Comparativo direto

Cenário JavaScript Rust
Reatribuir variável let x = 1; x = 2; let mut x = 1; x = 2;
Reatribuir constante const x = 1; x = 2; const X: i32 = 1; X = 2;
Alterar coleção const arr = []; arr.push(1); let mut v = vec![]; v.push(1);
Constante armazenada em memória em runtime embutida em compile-time (sem heap/stack)
Mutabilidade padrão mutável imutável
Escopo bloco bloco

Conclusão: intenção sobre conveniência

As duas linguagens adotam abordagens opostas à mutabilidade. JavaScript valoriza a flexibilidade, permitindo alterações livremente, a menos que sejam explicitamente restringidas. Rust valoriza a clareza, exigindo que o desenvolvedor declare sua intenção sempre que a mutabilidade for necessária.

Na prática, let mut em Rust se aproxima do let em JavaScript, enquanto o let puro de Rust não tem equivalente verdadeiro na linguagem. O const de JavaScript chega mais perto, mas é uma garantia mais frouxa: impede reatribuições, porém permite alterar os dados internos.

O modelo de Rust é mais rígido e explícito: let significa que nada pode mudar, e let mut significa que a mudança é permitida. Essa separação nítida transforma a mutabilidade em uma decisão de design consciente, não em um acidente de sintaxe, e é aí que Rust realmente se destaca.