Funciones que devuelven errores

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 }

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

A ratos, Manitas venía al taller del inventor y descansaba mientras Juanelo le “curaba” alguna avería menor, o le cambiaba piezas enteras gastadas por tanto esfuerzo y trabajo incesante. Como lo había reparado tantas veces tenía todos los repuestos para recomponerlo una y otra vez cuando hiciera falta. Hasta le tenía cariño a su creación. Era como un aprendiz que le quitaba mucho trabajo para que él pudiera seguir con los demás encargos…


Listas dinámicas - ArrayList
Genéricos
© 2025 Zen of Zig