expected block expression — Como Resolver em Zig

expected block expression — Como Resolver em Zig

O Que Este Erro Significa

O erro expected block expression ocorre quando o compilador Zig espera encontrar um bloco de código delimitado por chaves { }, mas encontra outra coisa. Blocos são fundamentais na sintaxe do Zig — são usados para corpos de funções, branches de if/else, corpos de while/for, e como expressões que produzem valores.

Causas Comuns

1. Corpo de Função Sem Chaves

fn dobrar(x: u32) u32
    return x * 2; // ERRO: expected block expression (faltam { })

2. If Sem Chaves (Zig Não Aceita)

Diferente de C, Zig exige chaves para blocos de controle:

pub fn main() void {
    const x: u32 = 5;
    if (x > 3)
        x = 10; // ERRO: expected block expression
}

3. While Sem Chaves

pub fn main() void {
    var i: u32 = 0;
    while (i < 10)
        i += 1; // ERRO: expected block expression
}

4. For Sem Chaves

pub fn main() void {
    const arr = [_]u32{ 1, 2, 3 };
    for (arr) |item|
        _ = item; // ERRO: expected block expression
}

5. Else Sem Chaves

pub fn main() void {
    const x: u32 = 5;
    if (x > 3) {
        // ...
    } else
        return; // ERRO: expected block expression após else
}

6. Confundir Sintaxe de Expressão com Statement

pub fn main() void {
    // Em Zig, if como statement precisa de bloco
    const x: u32 = 5;
    if (x > 3) return; // ERRO em alguns contextos
}

Note: Zig permite if (cond) return; em certos contextos, mas não para statements genéricos sem chaves.

Como Corrigir

Solução 1: Adicionar Chaves ao Corpo da Função

fn dobrar(x: u32) u32 {
    return x * 2; // Correto: corpo entre { }
}

Solução 2: Sempre Usar Chaves com if

pub fn main() void {
    var x: u32 = 5;
    if (x > 3) {
        x = 10; // Correto: bloco com chaves
    }
    _ = x;
}

Solução 3: Sempre Usar Chaves com while

pub fn main() void {
    var i: u32 = 0;
    while (i < 10) {
        i += 1; // Correto: bloco com chaves
    }
}

Para while com expressão de continuação:

pub fn main() void {
    var i: u32 = 0;
    while (i < 10) : (i += 1) {
        // corpo do loop
    }
}

Solução 4: Sempre Usar Chaves com for

pub fn main() void {
    const arr = [_]u32{ 1, 2, 3 };
    for (arr) |item| {
        _ = item; // Correto: bloco com chaves
    }
}

Solução 5: Chaves no else

pub fn main() void {
    const x: u32 = 5;
    if (x > 3) {
        // ...
    } else {
        return; // Correto: else com bloco
    }
}

Blocos como Expressões em Zig

Em Zig, blocos podem ser usados como expressões que produzem um valor usando labels:

pub fn main() void {
    const x = blk: {
        const a: u32 = 10;
        const b: u32 = 20;
        break :blk a + b; // O bloco "retorna" 30
    };
    _ = x; // x == 30
}

Isso é útil para cálculos complexos que precisam de variáveis temporárias.

Diferença entre Zig e C/C++

Em C/C++, blocos de uma linha sem chaves são permitidos:

// C/C++ — válido
if (x > 3)
    x = 10;

Em Zig, isso é sempre um erro. A decisão de exigir chaves foi intencional para evitar bugs como o famoso “goto fail” da Apple, onde indentação enganosa escondia um bug crítico de segurança.

// Zig — sempre use chaves
if (x > 3) {
    x = 10;
}

Padrões Comuns

Blocos de Uma Linha

Mesmo para blocos curtos, use chaves. A formatação em uma linha é aceitável:

if (x > 3) { return; }

Mas zig fmt normalmente expande para:

if (x > 3) {
    return;
}

Switch com Blocos

Cada braço do switch pode ter um bloco se precisar de múltiplas expressões:

fn processar(op: u8) u32 {
    return switch (op) {
        '+' => blk: {
            // lógica complexa
            break :blk 1;
        },
        '-' => 2,
        else => 0,
    };
}

Erros Relacionados

Continue aprendendo Zig

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