martes, 1 de junio de 2010

Nueva construcción para ciclos en Eiffel: across

En el libro Algoritmos, Objetos y Estructuras de Datos se explica detalladamente la estructura de ciclo en Eiffel. Posteriormente a la publicación del libro el lenguaje se vio ampliado con la introducción de una variante que permite un modo de programación seguro,  mas conciso, mas abstracto sin perder las cualidades del calidad de la sentencia loop (invariante y variante de ciclo).
Describiremos entonces lo que llamamos forma de itereación (across), el cual nos permite especificar iteraciones en forma mas compacta. La única condición es que la iteración se debe realizar sobre una estructura que herede de la clase ITERABLE. Todas las estructuras significantes de EiffelBase se han modificado para heredar de ITERABLE.
Para ir al grano vemos como sería la iteración sobre una lista:

Este mismo ejemplo usando la forma tradicional se escribe:

across mi_lista as lc loop print (lc.item) end

from my_list.start until my_list.off loop print (my_list.item) my_list.forth end

Analicemos las partes en que se divide la forma de iteración. Comienza con la "parte de iteración”:


across mi_lista as lc

Esta parte establece cual es la estructura sobre la que va a iterar (mi_lista) y además el cursor a usar (lc). La forma de iteración utiliza un cursor externo creado especialmente para la iteración y cuyo alcance  es sólo en la iteración.
Luego de la parte de iteración tenemos la parte del cuerpo de la iteración:

loop print (lc.item)

Esta parte utiliza el cursor para acceder al elemento apuntado en cada momento de la iteración. Nótese que no hay referencia a mover el cursor para adelante ni a controlar el fin de la lista (mi_lista.off). cómo en el caso tradicional . Todo esto es abstraído por la construcción y evita de esta manera errores de programación al respecto.
Una diferencia muy importante es que la forma de iteración utiliza un cursor externo mientras la forma tradicional (cómo la hemos escrito) usa un cursor interno. La generación automática de un cursor externo es ventajosa porque permite que la iteración no cambie el estado de la lista. Eso nos permite tener activos varios recorridos al mismo tiempo sin  afectarse entre si.
Si el cursor se crea automáticamente ¿cómo atravesamos la lista al revés?, es decir de atrás para adelante.. Una característica importante de la clase ITERABLE es la rutina new_cursor la cual devuelve un cursor nuevo recién creado asociado a la estructura. Este cursor es de tipo ITERATION_CURSOR que a su vez hereda de ITERABLE por lo cual podríamos escribir:

across mi_lista.new_cursor.reversed as c loop print (c.item) end

En el próximo artículo veremos el uso de la forma iterativa como expresión lógica.

No hay comentarios:

Publicar un comentario