Enum em Zig — O que é e Como Usar

Enum em Zig — O que é e Como Usar

Definição

Um enum (enumeração) em Zig é um tipo que define um conjunto fixo de valores nomeados. Cada valor é representado internamente por um inteiro, mas o compilador garante que apenas valores válidos sejam usados. Enums em Zig são mais poderosos que em muitas linguagens: suportam métodos, valores customizados e são a base das tagged unions.

Por que Enums Importam

  1. Legibilidade: Nomes descritivos em vez de números mágicos.
  2. Segurança de tipos: O compilador impede atribuição de valores inválidos.
  3. Switch exaustivo: O compilador garante que todas as variantes sejam tratadas.
  4. Métodos: Enums podem ter funções associadas, encapsulando lógica.

Exemplo Prático

Enum Básico

const std = @import("std");

const DiaDaSemana = enum {
    segunda,
    terca,
    quarta,
    quinta,
    sexta,
    sabado,
    domingo,
};

fn ehFinalDeSemana(dia: DiaDaSemana) bool {
    return switch (dia) {
        .sabado, .domingo => true,
        else => false,
    };
}

pub fn main() void {
    const hoje = DiaDaSemana.sexta;
    std.debug.print("É final de semana? {}\n", .{ehFinalDeSemana(hoje)});
}

Enum com Valores Explícitos

const HttpStatus = enum(u16) {
    ok = 200,
    created = 201,
    bad_request = 400,
    not_found = 404,
    internal_error = 500,
};

pub fn main() void {
    const status = HttpStatus.not_found;
    const codigo: u16 = @intFromEnum(status);
    std.debug.print("Status: {}\n", .{codigo}); // 404
}

Enum com Métodos

const Cor = enum {
    vermelho,
    verde,
    azul,
    amarelo,

    pub fn ehPrimaria(self: Cor) bool {
        return switch (self) {
            .vermelho, .verde, .azul => true,
            .amarelo => false,
        };
    }

    pub fn nome(self: Cor) []const u8 {
        return switch (self) {
            .vermelho => "Vermelho",
            .verde => "Verde",
            .azul => "Azul",
            .amarelo => "Amarelo",
        };
    }
};

pub fn main() void {
    const cor = Cor.azul;
    std.debug.print("{s} é primária? {}\n", .{ cor.nome(), cor.ehPrimaria() });
}

Enum como Índice de Array

const Direcao = enum { norte, sul, leste, oeste };

const deslocamento_x = std.EnumArray(Direcao, i32).init(.{
    .norte = 0,
    .sul = 0,
    .leste = 1,
    .oeste = -1,
});

pub fn main() void {
    const dx = deslocamento_x.get(.leste);
    std.debug.print("Deslocamento X para leste: {}\n", .{dx});
}

Conversões

// Enum para inteiro
const valor: u16 = @intFromEnum(HttpStatus.ok); // 200

// Inteiro para enum
const status = @enumFromInt(HttpStatus, 404); // .not_found

// Enum para string (nome do campo)
const nome = @tagName(DiaDaSemana.segunda); // "segunda"

Armadilhas Comuns

  • Switch não exaustivo: Sem else, o compilador exige todas as variantes. Isso é desejável — adicionar nova variante ao enum revelará todos os switches que precisam ser atualizados.
  • Conversão insegura: @enumFromInt com valor inválido causa comportamento indefinido. Valide o valor antes.
  • Confundir com strings: Enums não são strings. Use @tagName para obter o nome como string.
  • Usar else desnecessariamente: Evite else em switches de enum quando possível. Ele esconde variantes não tratadas.

Termos Relacionados

  • Tagged Union — Unions discriminadas baseadas em enum
  • Struct — Tipos estruturados
  • Union — Tipos union
  • Comptime — Enums podem ser usados em contexto comptime

Tutoriais Relacionados

Continue aprendendo Zig

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