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:
- !T o
- error{...}!T
- NombreError!T
|
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…