para Zig 0.15.2 Comprar

CAPÍTULO 8

Genéricos


Usamos argumentos genéricos cuando queremos crear funciones que puedan aceptar parámetros de distintos tipos. La sintaxis es la siguiente:


fn nombre_func ( T: type, x_a: T , … ,  ) tipo_devuelto //también puede ser T

o

fn nombre_func ( x_a: anytype , … ,  ) tipo_devuelto //también puede ser @TypeOf(x_a)


Este tipo de funciones, en realidad, tienen que ver con cómo el compilador de Zig reestructura el código fuente. Cuando definimos una función genérica y luego la usamos , el compilador la trata como una plantilla para generar una versión adaptada para cada tipo que aparece en las llamadas.

Ambas declaraciones especifican que el argumento x_a puede ser de diferentes tipos, según la llamada. Aún así, en el cuerpo de la función, hemos de tener en cuenta que al final operamos con un tipo concreto.

Los parámetros type y anytype son comptime de manera implícita. Si no fuera así el compilador no podría crear las versiones de la misma función en tiempo de compilación. Puedes, pero no necesitas escribir por delante de ellos la palabra comptime, aunque a veces la encontrarás escrita así en algunos tutoriales.

Solo cuando los argumentos no son type o anytype, es necesario poner la palabra comptime en las declaraciones y el compilador te avisará si no lo haces.

El inventor, entre otras cosas, estaba trabajando en una máquina voladora y en un arma nueva para el rey. La máquina voladora -por el riesgo que suponía probarla- seguía a medio hacer, pero el arma funcionaba casi a la perfección: al girar una manivela y soltarla, disparaba decenas de puntas de flecha. Eso sí, no paraba hasta agotar la carga.

load_ammo.zig

const std = @import("std");

const print = std.debug.print;

// puntas de flecha de distintos materiales

const Proyectile = enum {

    Wood,Iron,Steel,

    Copper,Rock,

};

// la ametralladora primitiva

const MachineGun = struct {

    a_magazine: [100]Proyectile = undefined,

    l_ammo: std.ArrayListUnmanaged(Proyectile) = .{},

    fn init(self: *MachineGun) void {

        self.l_ammo = std.ArrayListUnmanaged(Proyectile).initBuffer(&self.a_magazine);

    }

    // cargar diferentes cantidades / tipos de munición

    fn load_ammo(self: *MachineGun, x_ammo: anytype) void {

        // función anónima solo accesible desde este scope

        const load_single = struct {

            fn _(o_me: *MachineGun, x_bullet: anytype) void {

                if (o_me.l_ammo.capacity == o_me.l_ammo.items.len)

                    print("No hay más sitio\n", .{})

                else if (@TypeOf(x_bullet) == Proyectile)

                    o_me.l_ammo.appendAssumeCapacity(x_bullet)

                else

                    print("¡No puede disparar eso!\n", .{});

            }

        }._;

        // si es un array cargamos todos los elementos

        switch (@typeInfo(@TypeOf(x_ammo))) {

          .array => for (x_ammo) |o_bullet| load_single(self, o_bullet),

          else => load_single(self, x_ammo),

        }

    }

    // dispara todos los proyectiles

    fn shoot(self: *MachineGun) void {

        while (self.l_ammo.items.len > 0) {

            const o_bullet = self.l_ammo.pop();

            print("{any}\n", .{o_bullet});

        }

    }

};

pub fn main() !void {

    var o_mgun = MachineGun{};

    o_mgun.init();

    // cargar un proyectil

    o_mgun.load_ammo(Proyectile.Iron);

    // cargar algo que se encuentra en el suelo

    o_mgun.load_ammo("Algo que estaba en el suelo");

    // cargar una banda de proyectiles

    o_mgun.load_ammo([_]Proyectile{ .Copper, .Rock, .Steel });

    // disparar

    o_mgun.shoot();

}

$ zig run load_ammo.zig

zig run load_ammo.zig

¡No puede disparar eso!

.Steel

.Rock

.Copper

.Iron

Resumen del capítulo
Builtins de introspección
© 2025 - 2026 Zen of Zig