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.