Comptime em Zig — O que é e Como Usar
Definição
Comptime (abreviação de compile time, tempo de compilação) é um dos recursos mais poderosos e distintivos da linguagem Zig. Ele permite que código seja executado durante a compilação, não em tempo de execução. Com comptime, você pode avaliar expressões, gerar tipos, desenrolar loops e criar funções genéricas — tudo antes do programa rodar.
Diferentemente de macros em C/C++ ou templates em C++, comptime em Zig usa a mesma sintaxe da linguagem normal. Não existe uma “linguagem separada” para metaprogramação.
Por que Comptime Importa
- Genéricos sem custo: Funções genéricas são resolvidas em tempo de compilação, gerando código especializado.
- Eliminação de código morto: Condições avaliadas em comptime eliminam branches desnecessários do binário final.
- Validação antecipada: Erros de lógica podem ser capturados na compilação, não em produção.
- Zero overhead: Tudo que é resolvido em comptime não tem custo em runtime.
Exemplo Prático
Função Genérica com comptime
const std = @import("std");
fn maximo(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
pub fn main() void {
const resultado_int = maximo(u32, 10, 20);
const resultado_float = maximo(f64, 3.14, 2.71);
std.debug.print("Max int: {}\n", .{resultado_int});
std.debug.print("Max float: {d}\n", .{resultado_float});
}
O parâmetro comptime T: type obriga o compilador a resolver T durante a compilação. Isso gera duas versões especializadas da função — uma para u32 e outra para f64.
Bloco comptime
const std = @import("std");
const tabela = blk: {
var resultado: [10]u32 = undefined;
for (0..10) |i| {
resultado[i] = i * i;
}
break :blk resultado;
};
pub fn main() void {
// tabela já contém [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
// calculado em tempo de compilação!
std.debug.print("5² = {}\n", .{tabela[5]});
}
Condicional em Comptime
const builtin = @import("builtin");
const separador = if (builtin.os.tag == .windows) '\\' else '/';
Aqui, o compilador avalia a condição durante a compilação e elimina completamente o branch não utilizado.
Como Funciona
Quando o compilador Zig encontra comptime:
- Ele executa o código durante a fase de compilação.
- Variáveis
comptimedevem ser resolvidas sem depender de valores de runtime. - O resultado é “embutido” no binário como se fosse uma constante literal.
- Funções chamadas em contexto comptime não podem ter efeitos colaterais de runtime (I/O, alocação de heap, etc.).
Armadilhas Comuns
- Tentar usar valores de runtime em contexto comptime: Um parâmetro
comptimenão pode receber um valor que só é conhecido em tempo de execução. O compilador emitirá um erro claro. - Loops infinitos em comptime: O compilador tem um limite de avaliação. Loops muito grandes em comptime resultam em erro de compilação.
- Confundir
constcomcomptime:constapenas impede reatribuição;comptimegarante avaliação em tempo de compilação. - Efeitos colaterais: Chamar funções que fazem I/O em contexto comptime causará erro.
Termos Relacionados
- comptime_int — Tipo inteiro de precisão arbitrária em comptime
- comptime_float — Tipo float de alta precisão em comptime
- anytype — Parâmetro de tipo inferido
- Inline — Expansão inline de funções e loops