Inline em Zig — O que é e Como Usar

Inline em Zig — O que é e Como Usar

Definição

A palavra-chave inline em Zig serve para duas finalidades principais: forçar o inlining de funções e desenrolar loops em tempo de compilação. Quando aplicada a uma função, o corpo da função é substituído diretamente no local da chamada. Quando aplicada a um for ou while, o loop é desenrolado (unrolled), e cada iteração é “colada” sequencialmente no código gerado.

Por que Inline Importa

  1. Performance: Elimina o custo de chamada de função (push/pop de stack frame, salto).
  2. Comptime em loops: inline for permite iterar sobre tipos e valores em tempo de compilação.
  3. Otimização manual: Quando o compilador não faz inline automaticamente, você pode forçar.
  4. Metaprogramação: Combinado com comptime, permite gerar código especializado.

Exemplo Prático

Inline For (Desenrolamento de Loop)

const std = @import("std");

fn somaVetorial(vetor: @Vector(4, f32)) f32 {
    // Desenrola em 4 somas individuais em tempo de compilação
    var resultado: f32 = 0;
    const campos = [_]comptime_int{ 0, 1, 2, 3 };
    inline for (campos) |i| {
        resultado += vetor[i];
    }
    return resultado;
}

pub fn main() void {
    const v: @Vector(4, f32) = .{ 1.0, 2.0, 3.0, 4.0 };
    std.debug.print("Soma: {d}\n", .{somaVetorial(v)}); // 10.0
}

Inline For com Tipos (Metaprogramação)

const std = @import("std");

fn imprimir(args: anytype) void {
    inline for (std.meta.fields(@TypeOf(args))) |campo| {
        std.debug.print("{s}: {}\n", .{ campo.name, @field(args, campo.name) });
    }
}

pub fn main() void {
    imprimir(.{ .nome = "Zig", .versao = 13, .estavel = true });
}

Inline Function

// Forçar inlining — o corpo será copiado no local da chamada
inline fn max(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
    return if (a > b) a else b;
}

pub fn main() void {
    // Não há chamada de função no código gerado
    const resultado = max(@as(u32, 10), @as(u32, 20));
    std.debug.print("Max: {}\n", .{resultado});
}

Inline While

fn contar(comptime n: usize) [n]usize {
    var resultado: [n]usize = undefined;
    comptime var i: usize = 0;
    inline while (i < n) : (i += 1) {
        resultado[i] = i * i;
    }
    return resultado;
}

const quadrados = contar(5); // [0, 1, 4, 9, 16]

Inline vs Comptime

Aspectoinlinecomptime
FunçõesSubstitui corpo no local da chamadaExecuta inteiramente na compilação
LoopsDesenrola iteraçõesAvalia valores em compilação
ResultadoCódigo mais rápido, binário maiorConstante embutida no binário

Na prática, inline for frequentemente trabalha em conjunto com valores comptime:

inline for (comptime std.meta.fieldNames(MeuTipo)) |nome| {
    // cada iteração é resolvida em compilação
}

Armadilhas Comuns

  • Binário inchado: Funções inline muito grandes, chamadas em muitos lugares, aumentam o tamanho do binário significativamente.
  • Inline desnecessário: O compilador de Zig (via LLVM) já faz inlining automático quando vantajoso. Use inline explícito apenas quando necessário.
  • Confundir inline for com for normal: inline for requer que o iterável seja conhecido em comptime. Um slice dinâmico não pode ser usado com inline for.
  • Debug mais difícil: Código inline não aparece como chamada de função separada no stack trace.

Termos Relacionados

Tutoriais Relacionados

Continue aprendendo Zig

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