¿Qué es la metaprogramación?

En los últimos meses he estado cada vez mas ligado a C++, realmente no me pilla de nuevas pero si es cierto que en los ultimos tiempos mi produccion de codigo ha sido casi enteramente en Java.
La vuelta a C++ no me ha sentado nada mal, de hecho, he agradecido el dejar de hacer las mismas típicas aplicaciones de “Altas/Bajas/Modificaciones/Consultas”
En el refresco de C++, pude tener acceso a un libro que me prestó un compañero de trabajo. El libro en cuestión es “Modern C++ Design: Generic Programming and Design Patterns Applied” (http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315) de Alexei Alexandrescu. De momento solo he leido algunas paginas pero me ha servido para descubrir un mundo que hasta ahora no había explorado, la metaprogramación.
Es difícil simplificar algo como la metaprogramación en una sola frase, en una primera impresión, y como su propia palabra indica, es la programación sobre la programación, o también se puede ver como programas que construyen programas. Uno de los principales objetivos de esta técnica es llevar a tiempo de compilación cálculos que habitualmente se hacen en tiempo de ejecución.
Un claro ejemplo podría ser la construcción de una tabla de resultados, por ejemplo, si en nuestro programa necesitamos hacer una operación costosa, digamos una función matemática que exija mucho tiempo de cálculo, en lugar de llamar a dicha función en tiempo de ejecución, crearemos un código cuya salida sea los valores de esa función evaluada para diferentes valores y que sea usable desde nuestro programa, por ejemplo como la inicialización de un array con dichos valores.
== Ejemplo clásico ==
double funcion_costosa (int valor)
{
/* … */
}
cout << funcion_costosa(3);
== Ejemplo con técnicas de metaprogramación ==
double[] valores = {1.7862, 1.7652, 1.7890, 1.7675,….}; // Código generado con metaprogramming
cout << valores[3];
Como se puede ver en el ejemplo, si la optimización es nuestro objetivo, cuanto vamos a ganar usando técnicas de metaprogramacion en nuestros programas.
Ahora la pregunta es…¿y como puedo hacer eso? Realmente hay muchas técnicas para conseguir generar código, depende de la plataforma donde nos encontremos. La mayoría de estas técnicas recaen en preprocesadores o en los propios compiladores, concretamente en C++ una de las maneras de conseguirlo es usando plantillas.
Si algo me ha descubierto el libro que mencionaba al principio de la entrada es principalmente la flexibilidad y la potencia que tienen los “templates” en C++.
Un ejemplo habitual de metaprogramación en C++ usando plantillas suele ser el calculo de una serie de números, como por ejemplo el factorial, la serie de fibonacci o como vemos en el siguiente ejemplo, el desarrollo de la serie para calcular el valor de la función trigonometrica “seno”

En los últimos meses he estado cada vez mas ligado a C++, realmente no me pilla de nuevas pero si es cierto que en los ultimos tiempos mi produccion de codigo ha sido casi enteramente en Java.

La vuelta a C++ no me ha sentado nada mal, de hecho, he agradecido el dejar de hacer las mismas típicas aplicaciones de “Altas/Bajas/Modificaciones/Consultas”

En el refresco de C++, pude tener acceso a un libro que me prestó un compañero de trabajo. El libro en cuestión es “Modern C++ Design: Generic Programming and Design Patterns Applied” de Alexei Alexandrescu. De momento solo he leido algunas paginas pero me ha servido para descubrir un mundo que hasta ahora no había explorado, la metaprogramación.

Es difícil simplificar algo como la metaprogramación en una sola frase, en una primera impresión, y como su propia palabra indica, es la programación sobre la programación, o también se puede ver como programas que construyen programas. Uno de los principales objetivos de esta técnica es llevar a tiempo de compilación cálculos que habitualmente se hacen en tiempo de ejecución.

Un claro ejemplo podría ser la construcción de una tabla de resultados, por ejemplo, si en nuestro programa necesitamos hacer una operación costosa, digamos una función matemática que exija mucho tiempo de cálculo, en lugar de llamar a dicha función en tiempo de ejecución, crearemos un código cuya salida sea los valores de esa función evaluada para diferentes valores y que sea usable desde nuestro programa, por ejemplo como la inicialización de un array con dichos valores.

== Ejemplo clásico ==

double funcion_costosa (int valor)
{
   /* ... */
}
cout << funcion_costosa(3);

== Ejemplo con técnicas de metaprogramación ==

double[] valores = {1.7862, 1.7652, 1.7890, 1.7675,....}; // Código generado con metaprogramming
cout << valores[3];

Como se puede ver en el ejemplo, si la optimización es nuestro objetivo, cuanto vamos a ganar usando técnicas de metaprogramacion en nuestros programas.

Ahora la pregunta es…¿y como puedo hacer eso? Realmente hay muchas técnicas para conseguir generar código, depende de la plataforma donde nos encontremos. La mayoría de estas técnicas recaen en preprocesadores o en los propios compiladores, concretamente en C++ una de las maneras de conseguirlo es usando plantillas, y basándonos en técnicas como la especialización parcial y la recursividad.

Si algo me ha descubierto el libro que mencionaba al principio de la entrada es principalmente la flexibilidad y la potencia que tienen los “templates” en C++.

Un ejemplo habitual de metaprogramación en C++ usando plantillas suele ser el calculo de una serie de números, como por ejemplo el factorial, la serie de fibonacci o como vemos en el siguiente ejemplo, el sumatorio de los N valores:

template <int N>
struct Sumatorio
{
enum { result = N + Sumatorio<N-1>::result };
};
template <>
struct Sumatorio<0>
{
enum { result = 0 };
};
int sumatorio(int n) {
 return (n==0)? 0 : (n + sumatorio(n-1));
}
...
cout << Sumatorio<10>::result
...

Al compilar este ejemplo, el compilador se encargará de realizar la sustitución recursiva, de tal manera que en el código compilado la expresion Sumatorio<10>::result sera sustituido por “55”. Como vemos, la diferencia con realizar la llamada a la función sumatorio() es que si usamos templates, en tiempo de ejecución no se utilizará ni un ciclo de computación en calcular dicho sumatorio.

Si bien es cierto que mecanismos como estos tienen algunos inconvenientes como que por ejemplo hacen el código mas complicado de entender, desde el punto de vista del programador entrañan un bonito reto a acometer, cuyo principal objetivo puede ser la optimización. En mi opinión estos mecanismos añaden un poco de “picante” a la, a veces, monótona labor de programación.

Una respuesta a ¿Qué es la metaprogramación?

  1. jl dice:

    Sigue así… y mojate más. Pierde el miedo a mostrar TU relación con la programación. A que huelen los punteros

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: