Condicionales y bucles

Mediante las declaraciones de control de flujo de datos podemos crear bucles que ejecutan ciertas órdenes recurrentemente según ciertas condiciones.

Se trata de declaraciones de ejecuciones condicionales (if, case… when), bucles (for) y bucles condicionales (while).

Todas las declaraciones de flujo de control pueden formar bloques u ocupar una sola línea. Los de una sola línea siempre deben usar la palabra clave do entre la condición y las sentencias a ejecutar.

if, while y for pueden ser controlados con las palabras clave break y continue. Una instrucción de interrupción hará que el bucle termine inmediatamente.

Operadores

Para manejar este tipo de declaraciones usamos operadores aritméticos, relacionales y lógicos.

Operador Significado Ejemplo
+ suma a = 2 + 2
- resta a = 2 - 2
/ dividir a = 2 / 2
* multiplicar a = 2 * 2
% módulo (resto) a = 2 % 2
++ a = a + 1 a++
-- a = a - 1 a--
+= a = a + 2 a += 2
-+ a = a - 2 a -= 2
< menor que a < b
> mayor que a > b
<= menor o igual que a <= b
>= mayor o igual que a >= b
== igual que a == b
!= no igual que a != b
is igual que a is b
is not no igual que a is not b
and ambos son true (a > 2) and (a < 10)
or cualquiera es true (a > 2) or (b > 5)
not lo contrario de not (b)

if

if permite ejecutar una parte particular de código en base a una condición o conjunto de condiciones.

init
	a:int = 8
	if (a > 0) do print("a es mayor que 0")

En este código se cumple la condición a > 0, y en consecuencia al ejecutarlo escribirá en consola:

a es mayor que 0

Además con else podemos ordenar ejecutar una parte de código solo cuando no se cumple la condición de if.

init
	a:int = 0
	if (a > 0)
		print "a es mayor que 0"
	else
		print "a no es mayor que 0"

Con else if podemos añadir un número indefinido de condiciones.

init
	a:int = 0
	if a > 0 
		print "solo imprimo si a es mayor que 0"
	else if a is 0 
		print "solo imprimo si a es igual que 0"
	else 
		print "si no se cumple nada de los anterior imprimo que a es menor que 0"

while

init
	a:int = 10
	b:int = 0
	while a >= b
		print a.to_string()
		a--

En este ejemplo, se ejecutará el bloque while (imprimir en consola 'a' y restarle 1) una y otra vez mientras se cumpla la condición ( a >= b ). El resultado es que imprimirá en consola desde el 10 hasta el 0.

Otra forma de escribirlo:

init
	numero:int = 1
	do
		print "%i", numero
		numero++
	while numero <= 10

En este caso, escribe en consola desde el 1 al 10.

for

init
	for var num = 1 to 10 
		print "el numero es %d", num

En este código, dentro del bloque for se inicializa la variable 'num' cuyo valor asignado inicial es 1 y recorre del 1 al 10 cada vez que se ejecuta la instrucción y hasta que alcanza el último valor del rango. El resultado es:

 el numero es 1
 el numero es 2
 el numero es 3
 el numero es 4
 el numero es 5
 el numero es 6
 el numero es 7
 el numero es 8
 el numero es 9
 el numero es 10

Lo mismo también lo podemos escribir así:

init
	for var num = 1 to 10 do print ("el numero es %d", num)

También se puede iterar sobre los argumentos de un array o matriz de texto u otras colecciones que veremos más adelante. A modo de ejemplo:

init
	lista_colores: array of string = {"azul", "rojo", "verde"}
	for color in lista_colores
		print color

case ... when

La sentencia case…when ejecuta una sección de código cuando el valor de una condición cumple un criterio. El proceso se detiene tan pronto se encuentra la coincidencia y no se verifican el resto de posibilidades.

Case..when trabaja tanto con números como con cadenas de texto.

init
	var semaforo = "amarillo"
	case semaforo
		when "rojo"
			print "Para el coche"
		when "amarillo"
			print "Desacelera"
		default 
			print "Continua circulando"

Gestión de errores

Aunque estrictamente no se trata de una sentencia de control de flujo, me ha parecido oportuno incluirlo en este apartado puesto que conseguimos variar el flujo del programa en función de una determinada condición (aunque sea un error).

GLib tiene un sistema para gestionar excepciones llamado GError. Se trata de un sistema diseñado para hacer frente a ciertos errores específicos (por ejemplo, factores que no se conocen hasta que se ejecuta el programa y que no son vitales para su ejecución). Por eso, no se debe utilizar GError para otros problemas que pueden preverse (errores de código, como por ejemplo pasar un valor no válido a una función).

Una manera habitual de utilizar este sistema es con un bloque 'try…except' que nos permite detectar un error.

try
	fn("home/jamie/test")
except ex : IOError
	print "Error: %s", ex.message

Sin entrar demasiado en materia, podemos decir que en los errores podemos distinguir tres componentes:

  • Mensajes. Un texto sobre el error.
  • Dominios. Describen el tipo de problema. Por ejemplo IOError.
  • Código. Describe la variedad exacta del problema encontrado.Por ejemplo FILE_NOT_FOUND.

Cada dominio de error tiene uno o más códigos de error. Por ejemplo, exception IOError cuenta con FILE_NOT_FOUND, FILE_NO_READ_PERMISSION y FILE_IS_LOCKED.

También hay un bloque opcional llamado finally que se ejecuta siempre, independientemente de si se ha lanzado el error o no. Por ejemplo:

try
	icon = new Gdk.Pixbuf.from_file ("genie48.ico")
except e : GLib.Error
	stderr.printf ("Error: %s\n", e.message)
finally
	print "Debería verse un icono de la ventana"
🔝