Funciones que devuelven errores

para Zig 0.15.2 Comprar

Funciones que devuelven errores

Como los errores en Zig son valores, las funciones pueden devolver también un error.

Como ya vimos en el capítulo 6, cuando declaramos errores, en realidad estamos dando nombre a un set concreto de posibles errores.

  // tipo error para la torre

  const Failure = error{ Leak, Ungreased, Obstruction };

Esto nos va a permitir escribir funciones que pueden devolver o un resultado válido o uno de esos errores usando la sintaxis:

  fn has_failure(self: *const HTower) error{ Leak, Ungreased, Obstruction }!bool

o así:

  fn has_failure(self: *const HTower) !bool

o también así:

  fn has_failure(self: *const HTower) Failure!bool

Una vez terminadas, Manitas se pasaba largas horas revisando las torres. Detectaba y sellaba las fugas, engrasaba las piezas, y limpiaba la cal y otras impurezas que obstruían los cazos y los mecanismos. Si la reparación no llegaba, los errores se acumulaban con el paso del tiempo, estropeando la torre por completo.

sys_errors.zig

const std = @import("std");

const print = std.debug.print;

// tipo de error

const Failure = error{ Leak, Ungreased, Obstruction };

// torre desde el punto de vista de averías

const HTower = struct {

    a_failures: std.ArrayList(Failure),

    fn check_tower(self: *const HTower) bool {

        return self.a_failures.items.len == 0;

    }

    // función pura

    fn has_failure(a_failures_items: []const Failure, err_x: Failure) Failure!bool {

        for (a_failures_items) |err_fail|

            if (err_fail == err_x) return err_fail;

        return false;

    }

    fn get_random_err() Failure {

        return switch (std.crypto.random.intRangeAtMost(u2, 0, 2)) {

            0 => Failure.Leak,

            1 => Failure.Ungreased,

            2 => Failure.Obstruction,

            else => undefined,

        };

    }

    // simulador de fallos - método con efecto sobre la propiedad

    fn create_failure(self: *HTower, o_alloc: std.mem.Allocator) !void {

        const err_fail: Failure = get_random_err();

        if (has_failure(self.a_failures.items, err_fail)) |_|

            try self.a_failures.append(

                o_alloc,

                err_fail,

            )

        else |err_x|

            print("Fallo presente {}\n", .{err_x});

    }

};

inline fn get_current_time_ns() i128 {

    return std.time.nanoTimestamp();

}

const N_TOWERS = 20;

const N_DELAY = 3_000_000_000; // cada 3 horas (segundos)

// main puede devolver void o un fallo

pub fn main() !void {

    const o_alloc = std.heap.page_allocator;

    var a_towers = try std.ArrayList(HTower).initCapacity(o_alloc, N_TOWERS);

    for (0..N_TOWERS) |_| {

        try a_towers.append(o_alloc, HTower{

            .a_failures = std.ArrayList(Failure).empty,

        });

    }

    // tiempo

    var n_time = get_current_time_ns();

    while (true) {

        // comprobamos cada N_DELAY nano segundos

        if (get_current_time_ns() > (n_time + N_DELAY)) {

            n_time = get_current_time_ns();

            // se producen algunos fallos aleatorios

            for (a_towers.items) |*o_tower| {

                if (std.crypto.random.intRangeAtMost(u8, 0, 10) >= 9) {

                    try o_tower.create_failure(o_alloc);

                }

            }

            // listamos todos los errores

            for (a_towers.items, 0..) |o_tower, n_i|

                if (!o_tower.check_tower())

                    print(

                        "torre {}: {any}\n",

                        .{ n_i + 1, o_tower.a_failures.items },

                    );

            print("\n---------------------------------\n", .{});

        }

    }

}

~$ zig run sys_errors.zig

torre 6: { error.Obstruction }

torre 7: { error.Leak }

torre 8: { error.Leak }

torre 18: { error.Ungreased }

torre 20: { error.Ungreased }

---------------------------------


Listas dinámicas - ArrayList
Resumen del capítulo
© 2025 - 2026 Zen of Zig