Bucles while en Zig
Los bucles while son una de las estructuras de control de flujo más importantes en cualquier lenguaje de programación, y Zig ofrece una implementación robusta con características únicas. Vamos a explorar cómo funcionan los bucles while
en Zig y sus diversas variantes.
Bucle while básico
Un bucle while
en Zig tiene una sintaxis familiar: la palabra clave while
seguida de una condición entre paréntesis y un bloque de código que se ejecutará mientras la condición sea verdadera.
const expect = @import("std").testing.expect;
test "bucle while básico" {
var i: usize = 0;
while (i < 10) {
i += 1;
}
try expect(i == 10);
}
Interrumpir un bucle con break
Puedes salir de un bucle en cualquier momento utilizando la palabra clave break
:
test "while con break" {
var i: usize = 0;
while (true) {
if (i == 10) {
break;
}
i += 1;
}
try expect(i == 10);
}
Continuar a la siguiente iteración con continue
Zig ofrece una característica especial: la expresión continue
. Esta se ejecuta cada vez que el bucle completa una iteración o cuando se encuentra un continue
.
test "while con continue" {
var suma: usize = 0;
var i: usize = 0;
while (i < 10) : (i += 1) {
if (i % 2 == 0) {
continue; // Salta los números pares
}
suma += i;
}
try expect(suma == 25); // 1 + 3 + 5 + 7 + 9 = 25
}
While como expresión
Al igual que if
, los bucles while
en Zig también son expresiones y pueden devolver un valor. Cuando un bucle while
termina normalmente (sin ejecutar break
), el valor de retorno es el especificado en la cláusula else
. Si el bucle termina con break
, el valor pasado a break
se convierte en el resultado.
test "while como expresión" {
var encontrado = false;
const resultado = while (encontrado == false) {
encontrado = true;
break true;
} else false;
try expect(resultado == true);
}
Este es un ejemplo más práctico:
test "while para buscar un número" {
const numeros = [_]u32{ 2, 4, 6, 8, 10, 12 };
const encontrado = buscarNumero(numeros[0..], 8);
try expect(encontrado);
const noEncontrado = buscarNumero(numeros[0..], 7);
try expect(!noEncontrado);
}
fn buscarNumero(lista: []const u32, objetivo: u32) bool {
var i: usize = 0;
return while (i < lista.len) : (i += 1) {
if (lista[i] == objetivo) {
break true;
}
} else false;
}
While con opcionales
Similar a las sentencias if
, los bucles while
pueden trabajar con tipos opcionales. El bucle se ejecutará mientras el valor no sea null
:
test "while con opcionales" {
var iteraciones: usize = 0;
var valorOpcional: ?u32 = 10;
while (valorOpcional) |valor| {
try expect(valor == 10);
iteraciones += 1;
valorOpcional = null; // Termina el bucle
}
try expect(iteraciones == 1);
}
While con uniones de error
Los bucles while
también pueden trabajar con uniones de error, ejecutándose hasta que se encuentre un error:
const std = @import("std");
const expect = std.testing.expect;
test "while con uniones de error" {
var contador: usize = 0;
try secuenciaConError(3, &contador);
try expect(contador == 3);
}
fn secuenciaConError(max: usize, contador: *usize) !void {
contador.* = 0;
while (obtenerSiguiente(contador.*, max)) |valor| {
contador.* = valor;
} else |err| {
try expect(err == error.FinDeSecuencia);
}
}
fn obtenerSiguiente(actual: usize, max: usize) !usize {
if (actual >= max) {
return error.FinDeSecuencia;
}
return actual + 1;
}
Bucles while etiquetados
Puedes etiquetar los bucles while
para referenciarlos desde instrucciones break
o continue
en bucles anidados:
test "bucles while etiquetados" {
var contador: usize = 0;
externo: while (contador < 10) : (contador += 1) {
var j: usize = 0;
while (j < 10) : (j += 1) {
if (j >= 5) {
continue :externo; // Continúa con la siguiente iteración del bucle externo
}
}
}
try expect(contador == 10);
}
Bucle while en tiempo de compilación (inline while)
Zig permite desenrollar bucles en tiempo de compilación usando la palabra clave inline
:
test "inline while" {
comptime var i = 0;
var suma: usize = 0;
inline while (i < 5) : (i += 1) {
suma += i;
}
try expect(suma == 10); // 0 + 1 + 2 + 3 + 4 = 10
}
El bucle inline while
es útil cuando necesitas que la ejecución ocurra en tiempo de compilación, como cuando trabajas con tipos como valores de primera clase.
Los bucles while
en Zig combinan la familiaridad de otros lenguajes con características únicas como las expresiones continue
, while
como expresión y el manejo directo de opcionales y uniones de error. Estas capacidades hacen que los bucles sean más potentes y expresivos, permitiendo un código más conciso y legible.