cannot assign to constant — Como Resolver em Zig

cannot assign to constant — Como Resolver em Zig

O Que Este Erro Significa

O erro cannot assign to constant ocorre quando você tenta modificar o valor de uma variável declarada com const. Em Zig, const declara um valor imutável — uma vez atribuído, ele não pode ser alterado. Essa é uma decisão de design intencional: Zig favorece a imutabilidade por padrão, e você precisa usar var explicitamente quando precisa de mutabilidade.

Causas Comuns

1. Tentar Reatribuir uma Constante

pub fn main() void {
    const x = 10;
    x = 20; // ERRO: cannot assign to constant
}

2. Tentar Modificar Parâmetro de Função

Em Zig, parâmetros de função são sempre imutáveis:

fn incrementar(valor: u32) u32 {
    valor += 1; // ERRO: cannot assign to constant
    return valor;
}

3. Tentar Modificar Captura de for/while

pub fn main() void {
    var arr = [_]u32{ 1, 2, 3, 4, 5 };
    for (arr) |item| {
        item = item * 2; // ERRO: cannot assign to constant
    }
}

4. Tentar Modificar Captura de Optional

pub fn main() void {
    var opcional: ?u32 = 42;
    if (opcional) |valor| {
        valor = 100; // ERRO: cannot assign to constant
    }
    _ = opcional;
}

5. Tentar Modificar Elemento Via Slice Const

fn processar(dados: []const u8) void {
    dados[0] = 'X'; // ERRO: cannot assign — slice é const
}

6. Modificar Campo de Struct Const

const Ponto = struct {
    x: f64,
    y: f64,
};

pub fn main() void {
    const p = Ponto{ .x = 1.0, .y = 2.0 };
    p.x = 3.0; // ERRO: cannot assign to constant
}

Como Corrigir

Solução 1: Usar var ao Invés de const

Se a variável precisa ser modificada, declare-a com var:

pub fn main() void {
    var x: u32 = 10;
    x = 20; // OK: 'var' permite reatribuição
    _ = x;
}

Solução 2: Criar Cópia Local em Funções

Parâmetros são sempre const, então crie uma cópia local:

fn incrementar(valor: u32) u32 {
    var resultado = valor; // Cópia local mutável
    resultado += 1;
    return resultado;
}

Ou simplesmente:

fn incrementar(valor: u32) u32 {
    return valor + 1; // Sem necessidade de variável mutável
}

Solução 3: Usar Ponteiro em Capturas de for

Para modificar elementos de um array durante iteração, use captura por ponteiro:

pub fn main() void {
    var arr = [_]u32{ 1, 2, 3, 4, 5 };
    for (&arr) |*item| {
        item.* = item.* * 2; // OK: modifica via ponteiro
    }
}

Solução 4: Usar Ponteiro em Capturas de Optional

pub fn main() void {
    var opcional: ?u32 = 42;
    if (opcional) |*valor| {
        valor.* = 100; // OK: modifica via ponteiro
    }
    _ = opcional;
}

Solução 5: Aceitar Slice Mutável

fn processar(dados: []u8) void { // Sem 'const' no slice
    dados[0] = 'X'; // OK: slice mutável
}

Solução 6: Declarar Struct como var

const Ponto = struct {
    x: f64,
    y: f64,
};

pub fn main() void {
    var p = Ponto{ .x = 1.0, .y = 2.0 }; // 'var' permite modificar campos
    p.x = 3.0; // OK
    _ = p;
}

const vs var — Quando Usar Cada Um

Use const quando:

  • O valor não precisa mudar após a inicialização
  • Você está declarando constantes de configuração
  • É um valor calculado uma vez e usado várias vezes
  • Sempre que possível (é o padrão recomendado em Zig)

Use var quando:

  • O valor precisa ser atualizado em um loop
  • Você está construindo um resultado incrementalmente
  • A variável é um acumulador ou contador
  • O estado da variável muda ao longo da execução
const std = @import("std");

pub fn main() void {
    // Use const para valores que não mudam
    const limite = 100;
    const nome = "Zig";

    // Use var para valores que mudam
    var soma: u32 = 0;
    var i: u32 = 0;
    while (i < limite) : (i += 1) {
        soma += i;
    }

    std.debug.print("{s}: soma = {}\n", .{ nome, soma });
}

Filosofia do Zig: Imutabilidade por Padrão

O Zig favorece const por padrão por várias razões:

  1. Legibilidade: Ao ler código, você sabe que valores const não mudam
  2. Otimização: O compilador pode otimizar melhor quando sabe que valores são imutáveis
  3. Segurança: Previne modificações acidentais
  4. Concorrência: Valores imutáveis são intrinsecamente thread-safe

O compilador Zig inclusive emitirá um aviso se você declarar algo como var mas nunca modificá-lo, sugerindo que use const.

Erros Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.