CAPÍTULO 4
Bucles
A veces - de hecho muchas veces - querrás repetir una misma operación: por ejemplo para procesar cada elemento de un array o incrementar una variable varias veces consecutivas. Hasta ahora, hemos hecho más bien un flujo lineal de código, en el que las instrucciones se ejecutan una trás otra, sin repeticiones, como en este ejemplo:
linear_scores.zig |
|
const std = @import("std"); const print = std.debug.print; pub fn main() void { const a_scores = [_]u16{ 9000, 8000, 5000, 4200, 3800 }; print("\n", .{}); print(" ╔════════════════════════════╗\n", .{}); print(" ║ HIGH SCORES ║\n", .{}); print(" ║____________________________║\n", .{}); print(" ║ {}º | {} pts ║\n", .{ 1, a_scores[0] }); print(" ║ {}º | {} pts ║\n", .{ 2, a_scores[1] }); print(" ║ {}º | {} pts ║\n", .{ 3, a_scores[2] }); print(" ║ {}º | {} pts ║\n", .{ 4, a_scores[3] }); print(" ║ {}º | {} pts ║\n", .{ 5, a_scores[4] }); print(" ╚════════════════════════════╝\n", .{}); } |
|
$ zig run linear_scores.zig |
|
╔════════════════════════════╗ ║ HIGH SCORES ║ ║____________________________║ ║ 1º | 9000 pts ║ ║ 2º | 8000 pts ║ ║ 3º | 5000 pts ║ ║ 4º | 4200 pts ║ ║ 5º | 3800 pts ║ ╚════════════════════════════╝ |
En el ejemplo linear_scores.zig imprimimos línea a línea los valores del array a_scores que son las puntuaciones más altas de un juego. Funciona... Pero ¡qué rigidez! Hemos puesto a mano la posición y el score. Menos mal que han sido solo 5 - Imagina si tenemos que hacer lo mismo para 20, 30, 100 o 1000 elementos de una tabla. No parece una buena idea. Una pequeña mejora sería usar una variable para almacenar el índice (lo llamaremos n_i) e ir incrementando:
linear_scores_2.zig |
|
const std = @import("std"); const print = std.debug.print; pub fn main() void { const a_scores = [_]u16{ 9000, 8000, 5000, 4200, 3800 }; print("\n", .{}); print(" ╔════════════════════════════╗\n", .{}); print(" ║ HIGH SCORES ║\n", .{}); print(" ║____________________________║\n", .{}); var n_i: u8 = 0; print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); n_i = n_i + 1; print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); n_i += 1; print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); n_i += 1; print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); n_i += 1; print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); print(" ╚════════════════════════════╝\n", .{});
} |
|
$ zig run linear_scores_2.zig |
|
╔════════════════════════════╗ ║ HIGH SCORES ║ ║____________________________║ ║ 1º | 9000 pts ║ ║ 2º | 8000 pts ║ ║ 3º | 5000 pts ║ ║ 4º | 4200 pts ║ ║ 5º | 3800 pts ║ ╚════════════════════════════╝ |
Por cierto, para incrementar o decrementar una variable como n_i lo podemos escribir de dos maneras. La forma más larga es así:
|
// incrementamos n_i por 1 n_i = n_i + 1; // variable n_a la vamos a decrementar en 2 n_a = n_a - 2; |
O, más corto:
|
// incrementamos n_i por 1 n_i += 1; // variable n_a la vamos a decrementar en 2 n_a -= 2; |
Volviendo a nuestro programa de la tabla de puntuaciones, la situación ha mejorado un poco al tener el índice en una variable, pero seguimos repitiendo el mismo código una y otra vez. Las líneas:
|
print(" ║ {}º | {} pts ║\n", .{ n_i + 1, a_scores[n_i] }); n_i += 1; |
, se repiten una tras otra.
Seguro de que te da la sensación de que falta algo. Y sí - tienes razón - se puede hacer mucho más dinámico y más elegante, con recursividad e iteración.
Recursividad
Recursividad aquí es una palabra técnica para decir “ejecutar una función que después se vuelve a llamar a sí misma”.
Iteración
Iteración es “repetir un bloque de código pero sin escribirlo otra vez”:
- Saltando a una etiqueta,
- Mediante estructuras como los bucles for y while