Mario de Lama
malar@arrakis.es
http://www.arrakis.es/~malar
Antes de nada comentar que podemos escribir estas estructuras presionando muy pocas teclas: primero PRG y BRCH. A continuación la tecla deseada pero con desplazamiento izquierdo (primero tecla morada) para las estructuras NEXT o derecho (primero tecla verde) para las STEP.
Las estructuras iterativas, o bucles, se encargan de repetir un determinado código de programa una serie de veces. Hay dos tipos: Definidos e indefinidos. Los bucles definidos llevan asociados una variable contador en la que se especifica el número de veces que ha de repetirse el código. Hay dos tipos de bucles definidos, cada uno de ellos tiene dos variantes dependiendo de si el contador se incrementa de uno en uno o de forma definida por el programador.
Los bucles indefinidos se repiten hasta que una condición establecida se cumple o deja de cumplirse.
Definidas Indefinidas Cómo salir de un bucle definido cuando lo deseemos
'inicio' 'fin' START código a repetir NEXT
En el nivel 2: de la pila pondremos el valor inicial del contador y en 1: el valor final. A continuación se ejecuta el código tras lo que NEXT incrementa en uno el contador interno que crea el sistema operativo de la calculadora y comprueba su valor. Si es menor o igual que 'fin' se ejecuta de nuevo el código, si es mayor no se repite y el programa continúa. El bucle se repetirá 'fin - inicio + 1' veces.
\<< "H" "O" "L" "A" 1 3 START + NEXT "A" "M" "I" "G" "O" "/" "A" 1 6 START + NEXT \>>Este ejemplo nos deja en 2: la cadena "HOLA" y en 1: "AMIGO/A"
'inicio' 'fin' START código a repetir 'incremento' STEP
Esta estructura sólo se diferencia de la anterior en que se puede especificar un incremento distinto de 1, que era el único que podíamos tener con la anterior.
El incremento puede ser positivo o negativo (nunca cero ya que el bucle sería infinito), si usamos un algebraico o un nombre de variable como argumento de STEP se evalúa y su resultado es con el que STEP incrementa el contador. En caso de que el incremento sea negativo 'inicio' debe ser mayor que 'fin' deteniéndose el bucle cuando el contador es menor que el valor de 'fin'
\<< "H" "O" "L" "A" 1 0.2 START + -0.3 STEP "A" "M" "I" "G" "O" "/" "A" 0 1.12 START + '1-0.7' STEP \>>El resultado es el mismo que en el caso anterior.
'inicio' 'fin' FOR 'contador' código a repetir NEXT
Este bucle tiene la ventaja de que utilizamos una variable local como contador, esto nos permite acceder a él y recuperarlo en la pila o modificarlo. FOR toma el valor inicial y final del contador y además crea la variable local con el nombre que le suministramos delante. NEXT incrementa en 1 el contador y a continuación comprueba su valor volviendo a ejecutar la cláusula si es menor o igual que 'fin'. La variable local se destruye al terminar el bucle.
Es, sin duda alguna, el más utilizado de todos los bucles lo cual no quiere decir que sea el único a utilizar ya que si no tenemos necesidad de acceder al contador es mejor utilizar las estructuras START que son más simples y rápidas al no tener que crear la variable local.
\<< \-> z \<< FOR n z n ^ NEXT \>> \>>En la pila debe haber 3 números. El código "\-> z" guarda el valor de 1: en la variable local 'z' dejando en la pila el nivel 2: con el valor de 'inicio' y 1: con 'fin' para que los tome FOR. El bucle calcula distintas potencias de 'z' dependiendo de los valores 'inicio' y 'fin'
'inicio' 'fin' FOR 'contador' código a repetir 'incremento' STEP
Es la misma estructura anterior con la posibilidad de poder especificar el incremento deseado. Este puede ser también positivo o negativo y tiene todas las demás características que hemos visto en START ... STEP.
\<< 48 57 FOR x x CHR STR\-> SQ 2 STEP \>>Este ejemplo calcula el cuadrado de 0, 2, 4, 6 y 8
DO código a repetir UNTIL condicional END
En primer lugar se ejecuta el código que hay entre DO y UNTIL tras lo que se inicia la condición o test. Estos test no sólo pueden ser tales sino cualquier algebraico u operación que devuelva un resultado a la pila. Sea cual sea el test se entiende que el resultado es verdadero si en 1: hay un número distinto de 0. END evalúa cualquier algebraico o un nombre de variable que le demos como argumento.
Si el resultado del test es falso el bucle vuelve a ejecutarse, si es verdadero el programa continúa.
Esta estructura se utiliza cuando no sepamos las veces que ha de ejecutarse un código pero si sabemos que ha de realizarse, al menos, una vez.
\<< IF DEPTH 0 \=/ THEN 0 -> pila \<< DO 'pila' STO UNTIL DEPTH 0 == pila TYPE 8 == OR END IF pila TYPE 8 == THEN pila "Es un programa" ELSE "No hay programas" END \>> END \>>El ejemplo anterior comprueba en primer lugar si hay algún objeto en la pila, si no lo hay termina. Si lo hay, primero crea una variable local (pila) y a continuación empieza una estructura DO ... UNTIL que guarda en la variable local el contenido de 1: para seguidamente comprobar si queda algo en la pila o bien la variable contiene un programa. Si se cumple cualquiera de las dos condiciones el bucle termina, en caso contrario sigue ejecutándose hasta hacerlo. Finalmente comprobamos si en la variable hay un programa colocando una cadena en la pila que nos lo indique.
\<< IF DEPTH 0 \=/ THEN 0 \-> pila \<< IFERR DEPTH 1 SWAP START 'pila' STO IF 'pila' VTYPE 8 == THEN "" DOERR END NEXT THEN pila "Es un programa" ELSE "No hay programas" END \>> END \>>
WHILE condicional REPEAT código a repetir END
En esta ocasión el test lo valora REPEAT: si el resultado es verdadero ejecuta el código, en caso contrario el programa continúa tras END. Vemos, por tanto, que el código puede no ejecutarse nunca mientras en la anterior cláusula siempre se ejecutaba una vez por lo menos. Otra notable diferencia es que ahora se ejecuta el código si el resultado del test es verdadero.
\<< IF DEPTH 0 \=/ THEN \-> pila \<< WHILE DEPTH 0 \=/ pila TYPE 8 \=/ AND REPEAT 'pila' STO END IF pila TYPE 8 == THEN pila "Es un programa" ELSE "No hay programas" END \>> END \>>Vemos que el resultado de este programa es el mismo del anterior. ¿Cuál usar entonces? El que nos parezca más fácil en cada momento. El test de este último es más rebuscado que el del anterior y en general el programa es más confuso. En este caso yo elegiría la estructura DO ... UNTIL.
\<< IF DUP TYPE 3 == OVER SIZE SIZE 1 > AND THEN DUP SIZE EVAL \-> n \<< 1 SWAP FOR fila 1 n FOR columna DUP fila columna 2 \->LIST GET IF columna 1 == THEN 2 * ELSE 2 / END fila columna 2 \->LIST SWAP PUT NEXT NEXT \>> END \>>Este ejemplo nos permite multiplicar la primera columna de cualquier matriz por 2, y dividir las demás columnas por 2.