anytype em Zig — O que é e Como Usar
Definição
anytype é uma anotação de tipo especial em Zig que permite que o compilador infira o tipo de um parâmetro a partir do argumento passado na chamada da função. É o mecanismo principal para criar funções genéricas em Zig, substituindo a necessidade de sintaxes como <T> de outras linguagens.
Quando uma função aceita anytype, o compilador gera uma versão especializada para cada combinação de tipos usada. Isso é semelhante a templates em C++, mas com uma sintaxe mais simples e mensagens de erro mais claras.
Por que anytype Importa
- Genéricos simples: Cria funções que aceitam qualquer tipo sem boilerplate.
- Duck typing em comptime: O compilador verifica se o tipo suporta as operações usadas na função.
- Zero overhead: Cada especialização é compilada individualmente, sem indireção.
- Composição: Combina com
@TypeOfe@typeInfopara introspecção poderosa.
Exemplo Prático
Função Genérica com anytype
const std = @import("std");
fn dobrar(valor: anytype) @TypeOf(valor) {
return valor * 2;
}
pub fn main() void {
const a: u32 = dobrar(@as(u32, 21));
const b: f64 = dobrar(@as(f64, 1.5));
const c: i8 = dobrar(@as(i8, -10));
std.debug.print("u32: {}\n", .{a}); // 42
std.debug.print("f64: {d}\n", .{b}); // 3.0
std.debug.print("i8: {}\n", .{c}); // -20
}
anytype com Introspecção de Tipo
const std = @import("std");
fn imprimir(valor: anytype) void {
const T = @TypeOf(valor);
const info = @typeInfo(T);
switch (info) {
.int => std.debug.print("Inteiro: {}\n", .{valor}),
.float => std.debug.print("Float: {d}\n", .{valor}),
.pointer => |ptr_info| {
if (ptr_info.size == .Slice and ptr_info.child == u8) {
std.debug.print("String: {s}\n", .{valor});
} else {
std.debug.print("Ponteiro: {*}\n", .{valor});
}
},
.bool => std.debug.print("Bool: {}\n", .{valor}),
else => std.debug.print("Tipo: {s}\n", .{@typeName(T)}),
}
}
pub fn main() void {
imprimir(@as(u32, 42));
imprimir(@as(f64, 3.14));
imprimir(true);
}
Writer Genérico com anytype
const std = @import("std");
fn escreverSaudacao(writer: anytype, nome: []const u8) !void {
try writer.print("Olá, {s}! Bem-vindo ao Zig.\n", .{nome});
}
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try escreverSaudacao(stdout, "Brasil");
// Funciona com qualquer writer — arquivo, buffer, etc.
var buffer: [256]u8 = undefined;
var stream = std.io.fixedBufferStream(&buffer);
try escreverSaudacao(stream.writer(), "Mundo");
}
anytype vs comptime T: type
| Aspecto | anytype | comptime T: type |
|---|---|---|
| Sintaxe | Implícita | Explícita |
| Acesso ao tipo | Via @TypeOf(param) | Diretamente via T |
| Múltiplos parâmetros do mesmo tipo | Cada um pode ser diferente | Força o mesmo tipo T |
| Uso típico | Funções simples, writers | Contêineres, funções com tipo explícito |
Armadilhas Comuns
- Mensagens de erro: Quando
anytyperecebe um tipo que não suporta as operações da função, o erro pode ser confuso. Adicione@compileErrorpara mensagens claras. - Múltiplos anytype: Dois parâmetros
anytypepodem receber tipos diferentes. Se precisar forçar o mesmo tipo, usecomptime T: type. - Não é tipagem dinâmica:
anytypeé resolvido em comptime. Não existe dispatch dinâmico — cada uso gera código especializado. - Tipo de retorno: Use
@TypeOf(param)no tipo de retorno para que ele corresponda ao tipo do argumento.
Termos Relacionados
- Comptime — Execução em tempo de compilação
- comptime_int — Tipo inteiro em comptime
- Type Coercion — Conversão implícita de tipos
- Writer Interface — Padrão de interface genérica com anytype