Cheatsheet: Funções em Zig
Referência completa sobre declaração e uso de funções em Zig, incluindo genéricos, comptime e funções de ordem superior.
Declaração Básica
// Função simples
fn somar(a: i32, b: i32) i32 {
return a + b;
}
// Função pública (acessível de outros módulos)
pub fn calcular(x: f64) f64 {
return x * x;
}
// Função sem retorno
fn imprimir(msg: []const u8) void {
std.debug.print("{s}\n", .{msg});
}
// Função que pode falhar (retorna error union)
fn dividir(a: f64, b: f64) !f64 {
if (b == 0) return error.DivisaoPorZero;
return a / b;
}
// Função com conjunto de erros específico
const MathError = error{ DivisaoPorZero, Overflow };
fn dividirSeguro(a: f64, b: f64) MathError!f64 {
if (b == 0) return error.DivisaoPorZero;
return a / b;
}
// Função que nunca retorna
fn panico(msg: []const u8) noreturn {
@panic(msg);
}
Parâmetros
// Parâmetros são sempre imutáveis
fn processar(valor: i32) i32 {
// valor = 10; // ERRO: não pode modificar parâmetro
return valor + 1;
}
// Ponteiro para modificar valor
fn dobrar(ptr: *i32) void {
ptr.* *= 2;
}
// Slice como parâmetro
fn soma(numeros: []const i32) i64 {
var total: i64 = 0;
for (numeros) |n| {
total += n;
}
return total;
}
// Parâmetro comptime
fn criarArray(comptime N: usize) [N]i32 {
return [_]i32{0} ** N;
}
// Parâmetro anytype (genérico)
fn maximo(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
return if (a > b) a else b;
}
Retorno de Múltiplos Valores
// Retornar struct anônima (tupla)
fn divmod(a: i32, b: i32) struct { quociente: i32, resto: i32 } {
return .{
.quociente = @divTrunc(a, b),
.resto = @mod(a, b),
};
}
// Uso
const r = divmod(17, 5);
std.debug.print("Q={} R={}\n", .{ r.quociente, r.resto });
// Retornar array
fn minMax(slice: []const i32) [2]i32 {
var min = slice[0];
var max = slice[0];
for (slice[1..]) |v| {
if (v < min) min = v;
if (v > max) max = v;
}
return .{ min, max };
}
Funções Genéricas
// Função genérica com anytype
fn trocar(a: anytype, b: @TypeOf(a)) void {
_ = a;
_ = b;
}
// Função genérica com tipo comptime
fn List(comptime T: type) type {
return struct {
items: []T,
len: usize,
const Self = @This();
pub fn get(self: Self, index: usize) T {
return self.items[index];
}
};
}
// Uso
const IntList = List(i32);
_ = IntList;
// Genérico com restrições via @typeInfo
fn somar_generico(comptime T: type, a: T, b: T) T {
const info = @typeInfo(T);
switch (info) {
.int, .comptime_int => return a + b,
.float, .comptime_float => return a + b,
else => @compileError("Tipo não suportado para soma"),
}
}
Funções de Ordem Superior
// Tipo de ponteiro de função
const Operacao = *const fn (i32, i32) i32;
fn aplicar(op: Operacao, a: i32, b: i32) i32 {
return op(a, b);
}
fn somar(a: i32, b: i32) i32 { return a + b; }
fn multiplicar(a: i32, b: i32) i32 { return a * b; }
// Uso
const resultado1 = aplicar(somar, 3, 4); // 7
const resultado2 = aplicar(multiplicar, 3, 4); // 12
// Map genérico
fn map(
comptime T: type,
comptime R: type,
items: []const T,
f: *const fn (T) R,
resultado: []R,
) void {
for (items, 0..) |item, i| {
resultado[i] = f(item);
}
}
// Filter genérico
fn filter(
comptime T: type,
items: []const T,
pred: *const fn (T) bool,
resultado: []T,
) []T {
var count: usize = 0;
for (items) |item| {
if (pred(item)) {
resultado[count] = item;
count += 1;
}
}
return resultado[0..count];
}
Métodos (Funções em Structs)
const Retangulo = struct {
largura: f64,
altura: f64,
// Método de instância (recebe self)
pub fn area(self: Retangulo) f64 {
return self.largura * self.altura;
}
// Método que modifica (recebe ponteiro para self)
pub fn escalar(self: *Retangulo, fator: f64) void {
self.largura *= fator;
self.altura *= fator;
}
// Método "estático" (não recebe self)
pub fn quadrado(lado: f64) Retangulo {
return .{ .largura = lado, .altura = lado };
}
};
// Uso
var r = Retangulo{ .largura = 5.0, .altura = 3.0 };
const a = r.area(); // chamada de método
r.escalar(2.0); // modifica r
const q = Retangulo.quadrado(4.0); // "construtor"
_ = a;
_ = q;
Inline e Comptime
// Função inline
inline fn fast_add(a: i32, b: i32) i32 {
return a + b;
}
// Função comptime
fn fibonacci(comptime n: u32) comptime_int {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
const fib10 = fibonacci(10); // calculado em tempo de compilação
// Bloco comptime dentro de função
fn inicializar() [256]u8 {
comptime {
var tabela: [256]u8 = undefined;
for (&tabela, 0..) |*elem, i| {
elem.* = @intCast(i);
}
return tabela;
}
}
Defer em Funções
fn processarArquivo(path: []const u8) !void {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close(); // fecha ao sair, independentemente de como
const data = try file.readToEndAlloc(allocator, max_size);
defer allocator.free(data); // defers executam em ordem LIFO
errdefer std.log.err("Falha ao processar: {s}\n", .{path});
// errdefer só executa se função retornar erro
try processar(data);
}
Recursão
// Recursão simples
fn fatorial(n: u64) u64 {
if (n <= 1) return 1;
return n * fatorial(n - 1);
}
// Recursão com comptime
fn gerarTipo(comptime depth: usize) type {
if (depth == 0) return i32;
return struct {
valor: gerarTipo(depth - 1),
};
}
Padrões Comuns
// Função init / deinit (construtor / destrutor)
const Buffer = struct {
data: []u8,
allocator: std.mem.Allocator,
pub fn init(allocator: std.mem.Allocator, size: usize) !Buffer {
return .{
.data = try allocator.alloc(u8, size),
.allocator = allocator,
};
}
pub fn deinit(self: *Buffer) void {
self.allocator.free(self.data);
}
};
// Uso
var buf = try Buffer.init(allocator, 1024);
defer buf.deinit();
// Função com contexto (closure simulada)
fn criarContador() struct {
valor: i32,
pub fn incrementar(self: *@This()) i32 {
self.valor += 1;
return self.valor;
}
} {
return .{ .valor = 0 };
}
Tabela de Referência
| Padrão | Exemplo |
|---|---|
| Função simples | fn f(x: i32) i32 |
| Função pública | pub fn f() void |
| Retorna erro | fn f() !i32 |
| Erro específico | fn f() MyError!i32 |
| Nunca retorna | fn f() noreturn |
| Parâmetro genérico | fn f(x: anytype) @TypeOf(x) |
| Parâmetro comptime | fn f(comptime T: type) type |
| Ponteiro de função | *const fn (i32) i32 |
| Método | fn f(self: Self) void |
| Método mutável | fn f(self: *Self) void |
| Inline | inline fn f() void |
Veja Também
- Sintaxe Básica — Fundamentos da linguagem
- Error Handling — Tratamento de erros detalhado
- Comptime — Metaprogramação em tempo de compilação
- Structs — Métodos e tipos associados
- Padrão Factory — Padrão de criação com funções