No sé muy bien a qué while() te refieres porque nombras elementos de los dos. No importa, te detallo el significado de los dos.
En efecto, el bucle while() se ejecuta mientras la condición que pongamos dé un valor verdadero.
Antes de seguir, hay que aclarar que en Perl, un valor verdadero es aquel que no es falso. Esto parece una tontería, pero resulta que es más fácil describir los valores de verdad o falsedad empezando por los falsos. Sacado de perldoc perlsyn:
Using text Syntax Highlighting
Verdad y falsedad
El número 0, las cadenas '0' y "", la lísta vacía "()" y el "undef" son
todos falsos en contexto booleano. Todos los demás valores son verdaderos.
La negación de un valor verdadero, por medio de "!" o "not" devuelve un
valor falso especial. Cuando se evalúa como cadena, se le trata como "",
pero como número, se le trata como 0. La mayor parte de los operadores que
devuelven verdadero o falso se comportan de esta manera.
Coloreado en 0.000 segundos, usando
GeSHi 1.0.8.4
El primer while() es:
Using perl Syntax Highlighting
while ($fin_generacion == 0) {
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
Literalmente, dice: "haz el bucle mientras $fin_generación sea 0".
La variable $fin_generacion es en realidad un indicador (bandera), que se inicializa en la línea 8, y se modifica en la línea 37 para indicar que el bucle while() debe terminar. En ese línea se establece $fin_generacion a 1, por lo que al volver a probar la condición de la línea 16, ya no se cumple (1 no es igual a 0), y el bucle while() termina.
Del segundo while():
Using perl Syntax Highlighting
while ($i < $longitud and not $incremento) {
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4
La condición dice: "haz el bucle mientras que a) $i sea inferior a $longitud, y b) no-$incremento sea verdadero".
La primera parte está clara: usamos $i como un índice, y no queremos sobrepasar la $longitud de los arrays. El tema complicado puede estar en la segunda parte. Desarrollándolo mejor:
"no-$incremento sea verdadero" es lo mismo que "$incremento sea falso".
Estamos en el mismo caso que el primer while(): $incremento se usa como bandera, y se inicializa a 0. De esa manera, entra en el bucle while. "not $incremento" resuelve a verdadero, por lo que se cumple esa parte de la condición, y entra. Cuando, más tarde, en la línea 32, la variable $incremento se pone 1, al llegar de nuevo a la condición, resuelve en "not 1", es decir, "falso", y como se trata de un "and", toda la condición es falsa, y el bucle termina.
Hoy en día se recomienda dar mejores nombres a este tipo de variables. Por ejemplo, la primera $fin_generacion, yo le cambiaría el nombre a $estamos_generando, y la inicializaría a 1, para luego ponerla a 0 en mitad del programa. Y para $incremento, la llamaría $hay_incremento.
Esta es mi propia versión. Aunque veas en el código cosas muy raras, te aseguro que no hay nada de "magia".
Using perl Syntax Highlighting
#!/usr/bin/env perl
use utf8;
use strict;
use warnings;
sub variaciones {
# Parámetros
my($inicio, $fin, $longitud) = @_;
# Variables locales
my @resultado;
# 1. Inicializa la semilla
my @semilla = ($inicio) x $longitud;
# 2. Genera las variaciones
my $hay_incremento; # nos avisa de si se incrementó @semilla o no
do {
$hay_incremento = 0; # de momento, no lo hay
# Almacena la variación actual (una copia de la semilla que tenemos en este momento)
push @resultado, [ @semilla ];
for (my $i = 0; $i < $longitud; $i++) { # por toda la $longitud de la @semilla
if ($semilla[$i] == $fin) { # si el elemento llegó a $fin
$semilla[$i] = $inicio; # lo ponemos al valor $inicio
# y el bucle continúa con el siguiente
# elemento de @semilla
}
else {
$semilla[$i]++; # incrementamos el elemento
$hay_incremento = "sí, lo hay"; # y lo marcamos
last; # terminamos el bucle, no hay que hacer más
}
}
} while ($hay_incremento);
# 3. Retorna el resultado
return \@resultado;
}
my $resultado_ref = variaciones(0, 4, 2);
for my $variacion_ref (@$resultado_ref) {
print "(", join(", ", @$variacion_ref), ") ";
}
print "\n";
Coloreado en 0.002 segundos, usando
GeSHi 1.0.8.4
Como puedes ver, siempre se intenta que el código sea legible, casi como si fuera algo literario, como el caso de
Using perl Syntax Highlighting
} while ($hay_incremento);
Coloreado en 0.001 segundos, usando
GeSHi 1.0.8.4