Hola monchito_elroro,
No te preocupes demasiado por el tema de los bucles, si recién estás empezando es lógico que te cueste apreciar si hay código redundante. A todos nos pasó (y/o nos sigue pasando) alguna vez.
Yo antes hacía redundancias como éstas:
if Encontrado = true
then ....
Que puede mejorarse:
En el tema de los ciclos es algo más difícil. Pasa más por una organización de nuestras ideas, de desarrollar la lógica y algoritmia. Lamentablemente (o afortunadamente, según como mires) sólo hay un modo de aprender y mejorar: ¡seguir practicando! A medida en que avanzas tu cabeza gana puntos, se va acostumbrando y hasta te diría que algunas cosas se vuelven triviales, básicas y te salen espontáneamente. Así es que vas a encontrar, y desarrollar, en el ejercicio diario consejos, tips y "trucos" que te ayudan hacer de la programación algo más gratificante.
En lo particular, en lo que hace a ciclos yo diría que deben recordarse algunas reglas de oro:
1) Volver a los fundamentos de programación y repasar los conceptos y características de cada ciclo:
A. While: requiere de una condición de entrada, y de no cumplirse no se ejecuta. Por tanto por definición si inicialmente no se satisfacen las condiciones ¡no se entra al ciclo!
Pregúntate si realmente el ciclo ha de ejecutarse, o es algo meramente opcional.
B. Repeat: por naturaleza se ejecutará al menos una vez y requiere una condición de salida. Si en verdad el ciclo ha de llevarse a cabo, lo mejor es optar por repeat o, si se saben las condiciones finales e iniciales por el for.
Por ejemplo, muchas veces nos encontramos, y nos sale más fácil, con esto:
encontrado = false;
while NOT encontado do
begin
...
end;
Observa que ha sido necesario forzar al código a entrar al ciclo haciendo que la condición se cumpla, y además en la condición se está introduciendo un negado (en lo posible debe evitarse una evaluación por los negados). Es mucho más limpio su contraparte:
repeat
....
until encontrado
Observa que no ha sido necesario valores iniciales, no hay código forzoso. Como el ciclo siempre ha de tener lugar, con el repeat me aseguro de ello.
C. For: es ciclo más simple, y elemental, que se ejecutará una cantidad conocida de veces gracias a que se conocen los valores finales e iniciales de la variable de iteración.
Recomiendo la lectura de libros sobre algoritmia.
2. En parte relacionado con (1), evita en lo posible añadir cláusulas de escape como Exit, Continue que provoquen la ruptura prematura y la ejecución normal del ciclo. Si se puede saber y evaluar cuando ha de finalizar un ciclo, es mejor que esté como una condición y no como una salida forzada. Ejemplos típicos que veo:
for i := 0 to Count - 1 do
begin
// algo de código
if (condicion)
then begin
// algo para la condición
exit;
end;
end;
Si lo analizamos friamente, si realmente es necesario dar por finalizado el ciclo ante el cumplimiento de una condición, ¡que ésta nos de la salida! Y no parte de la lógica del problema. Cambie el ciclo por un while o repeat según lo más adecuado:
repeat
// algo de código
inc(i)
until condicion OR (i = Count)
Y si es necesario obviar alguna iteración, por naturaleza del problema, es aceptable el uso de Continue. Dentro de todo es algo tolerable, pero si se puede evitar su uso, mejor.
La lección es:
antes de finalizar un ciclo fuera de su naturaleza ¡piénselo dos veces!
3. Resulta algo curioso, en términos semánticos es mucho más fácil pensar en un repeat: "repetir algo hasta que..."; pero por alguna razón que no logro entender del todo, nos resulta más fácil pensar al momento de codificar en un while, cuya semántica es más liosa: "mientras ... hacer algo"
Con un repeat vemos efectivamente la condición de salida mientras que con el while la invertimos y la hacemos más oscura.
Piensa en salidas y luego en entradas. Recuerda:
¡Los ciclos deben terminar!
Si sólo pensamos en entradas, nos centramos más en un while. Tan es ese apego al while que en muchas veces el repeat es dejado de lado, y ni que decir... ¡hasta no reconocido!
Es decir: tendemos a hacer el doble de trabajo: reconocemos las salidas, pero la transformamos en una condición de entrada y ahora el código se adapta a esta nueva lógica.
No se porqué... pero es curioso, si das a elegir a muchos desarrolladores entre un while y un repeat que no te sorprenda si más de la mitad se inclina por el while. Yo tengo una teoría: como este requiere de una condición como entrada lo ven y sienten como un medio seguro en vez de delegarla para el final.
La lección: aprende a reconocer y practicar los tres ciclos. No te quedes únicamente con for y while. Hay mucho código escrito en while que con repeat sería mucho más claro. De hecho la realidad es que
si tienes un ciclo y resulta ser que tus ideas todavía no te cuadran y cierran, ¡prueba con su contraparte!
Esto es apoyado por algo que comenté en paréntesis antes: evitar una lógica basado en negados.
Si tienes muchos NOT, es un síntoma de que lo estás pensando al revés.
Con estos principios elementales, seguro que ahora tendrás las cosas más fresca, y estás más abierto a nuevas formas de hacer código.
4. Todo ciclo while y repeat es invertible. Es decir que un while se puede hacer en un repeat y a la inversa, un repeat en un while. Practica, por diversión, de vez en cuando pasando de uno a otro. Esto ayuda a que la cabeza recalibre y se entrene más.
5. Ten respeto a los ciclos, después del IF es la segunda estructura de control que más se utiliza. De hecho, cerca del 35% del código está compuesto por algún ciclo, sea for, while o repeat. Es mejor darle tiempo a revisarlo antes que confiarnos. Y si le sumamos las cláusulas de escape... ¡ni que decir, que hace más difícil hacer trazas al código!
Saludos,