Publicidad

domingo, 12 de octubre de 2008

Reflexión y Metaprogramación

En mi entrada anteriór, definé un metaprograma como un programa que genera otros programas y escribí que reflexión es diferente que metaprogramación porque se trata de ejecución, como un intérprete y no de generación de un otro programa, como un compilador. Hoy queiro examinar de nuevo las definiciones y mostrar que reflexión, si, puede ser un caso especial de metaprogramación. También queiro impartar una idea más claro sobre como reflexión funciona.

El prefixo “meta-”, en el sentido moderno, quiere decir “sobre (su própria categoría)” (http://en.wikipedia.org/wiki/Meta). O sea, quiere decir que algo tiene la categoría de si mismo como objeto, ou algo de esta categoría. En este sentido, un metaprograma es un programa que tiene como objeto un programa, sea un otro programa o si mismo. En el último caso se denomina “reflexión”.

¿O que quiere decir que algo es un objeto? Que se puede ser representado y manipulado. Para un programa tener el poder de manipular si mismo o un otro programa, tiene que tener el poder de representar y manipular los elementos del programa, tal como bloques de código, clases, métodos, protocolos, etc. De los elementos que se puede manipular sin restricción se denominan “objetos de primera" (http://en.wikipedia.org/wiki/First-class_object#cite_note-0)

Cualquier programa en cualquier lenguaje puede facilmente manipular datos (siendo en si mismo representaciones), pues los lenguajes son construidos para hacer esto. Los métodos sirven para modificar los datos (que normalmente refieren a cosas fuera del programa). El método tiene aceso a los datos, sea porque son globales o porque reciben los datos como argumentos. El método manipula los datos, y (en el caso que no son globales) regrese los datos al método que lo llamó.

Programas Que Modifican Sus Elementos

Unos lenguajes, como LISP y Scheme habilitan que se pase no solo datos al método, si no bloques de código, clases, métodos, protocolos, etc. Asi, se puede modificar estos últimos y, en efecto, modificar el programa. O sea, se puede definir un método capaz de generar o modificar otros métodos. Por ejemplo, se puede definir métodos abstratos que toman como argumentos metodos simples y construyan de ellos un método compuesto, que el método dá como salida, ou que descomponen métodos compuestos, criando mas simples métodos. O se puede definir un método que agrega métodos nuevos a un clase. Entonces, un clase, también puede ser pasado como un argumento a un método y regresado en forma modificado.

Programas Dinámicos: Programas Cuya Ejecución Pueden Variar

Una otra manera de variar la ejecución de un programa depende en lo que pasa en el tiempo de ejecución es dejar abierto cuales métados se van a llamar o por cuantos ciclos se va a procesar unos datos entrados por el usuario. Por ejemplo, un programa puede usar declaraciones de if.. o case.. para responder diferencialmente cuando un usario selecciona un item de un menu, o el programa puede usar un ciclo de for i =0 to string.size() para dejar abierto por cuantas veces operar en una cadena entrada por el usuario hasta que se sabe el tomaño de la cadena. O se puede definir más que un método con el mismo nombre pero donde cada variación usa diferentes argumentos (sean un número diferente de argumentos o argumentos de diferentes tipos o clases). Depende en la acción del usuario, los tipos o números de argumentos cambien y entonces el método llamado cambia.

Reflexión

¿Como es que se puede habilitar metaprogamación dinámica? Un programa que modifica sus elementos tal como métodos, etc, es un metaprograma, pero no es necesariament dinámico, pues su comportamiento puede ser determinado en el tiempo de compilación. Y los ejemplos arriba de programas dinámicos no son ejemplos de metaprogramación, pues los elementos del programa no se cambien.

Reflexión combina los dos aspectos de la metaprogramación dinámica, metaprogramción y dinamismo, y agrega un elemento más, datos sobre (o sea, una representación de) su próprio estructura y su próprio ejecución. Cualquier programa dinámico deja su comportamiento variar de acuerdo con datos entrados por un usuario, un servidor, etc. Con reflexión, el comportamiento de un programa varia de acuerdo con datos sobre el próprio programa y el comportamiento del próprio programa en el tiempo de ejecución.

Un contador de ciclos como metadata de reflexión
Creo que se puede tomar como un ejemplo muy sencillo de reflexión un contador de ciclos usado dentro del ciclo para determinar cuando terminar el próprio ciclo. Se puede ver el contador como una representación de lo que está sucediendo durante la ejecución del ciclo y la própria representación de número de ciclos sirve para módificar el número de ciclos ejecutado, pués la ejecución del ciclo para cuando la representación muestra que el número ha llegado al máxico del ciclo. Asi, la representación sirve para afectar la realidad representada.

En efecto, cuando un programa tiene y usa un variable como el contador descrito arriba, aquel programa está pidiendo del intérprete (lo cual es el entorno de ejecución en el caso de lenguajes compilados) que esto use el variable para monitorear y controlar el comportamiento durante ejecución del aspecto representado por el variable. En el caso del contador de ciclos, el programa pide del intérprete que no deje el número de ciclos pasar el máximo querido.

Reflexíon, entonces funciona asi: Un aspecto del programa a ser monitoreado es representado dentro del programa como variable. El intérprete debe (a) modificar el valor del variable de acuerdo con la ejecución, (b) leer el valor del variable, c) comparar el valor con lo que el programa dice que tiene que pasar y d) modificar la realidad ejecutado conforme con b) y c).

De hecho, el ejemplo del contador de ciclos no es claramente un caso de metaprogramación, pues la única cosa representada y modificada es el número de ciclos ejecutado y esto normalmente no se considera uno de los elementos básicos de un programa, tal como los métodos, clases, etc. No obstante, unos lenguajes como Java extienden está idea de reflexión y habilitan la representación de otros datos sobre un programa y su ejecución, tales como cuales clases estan siendo instanciados, cuales son sus miembros y la estructura semántica del programa. Si entiendo bien, la idea es parecido. En el caso del contador, el intérprete monitorea el contador y modifica la cosa contado, por media de terminar el ciclo cuando llega al maximo querido. En casos de monitorear clases, métodos, etc. el intérprete modifica ellos, ou por los menos (pues, todo de esto ocurre despues de la compilación) actua como se fueran diferentes en el programa.

En el caso de un contador de ciclos es fácil entender como la realidad de ciclos puede ser representada dentro de un programa y como se puede modificar la realidad de número de ciclos realmente ejecutado. En otros casos no es tan fácil entender lo que es posible representar y como se puede modificar la cosa representada. De hecho, yo no entiendo bien como reflexión funciona en los otros casos. Pero me parece que todos deben ser de acuerdo, más o menos, con el padrón de reflexión descrito arriba.

Para alguién que quiere entender al fondo lo que es reflexión y lo que es para un programa representarse a si mismo, alguién con el tiempo (lo que no lo tengo), las ganas y ha habilidad con el inglés, le sugiero la tésis original del fondador de la área de reflexión, Brian Cantwell Smith, titulada "Reflection and Semantics in a Procedural Language", disponível como PDF para bajar a (http://library.readscheme.org/page11.html).

1 comentario:

jimmy dijo...

That good that you followed with the subject of metaprogramacion, since also I am interested, and then not habia leido this. It leaves we see ourselves. Kindly: Christian Lopez