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
- Legibilidade: Nomes descritivos em vez de números mágicos.
- Segurança de tipos: O compilador impede atribuição de valores inválidos.
- Switch exaustivo: O compilador garante que todas as variantes sejam tratadas.
- 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:
@enumFromIntcom valor inválido causa comportamento indefinido. Valide o valor antes. - Confundir com strings: Enums não são strings. Use
@tagNamepara obter o nome como string. - Usar
elsedesnecessariamente: Eviteelseem 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