miércoles, 28 de octubre de 2009

Macros vs Funciones

Recapitulando

En el último post dedicado a las macros dije que:

En general queremos proteger los símbolos. Una macro debe ser higiénica y transparente por defecto.

Si queremos definir un símbolo en el entorno de llamada, querremos que un símbolo sea no-higiénico. Usualmente este símbolo deberá ser pasado por argumento para controlar qué se ensucia en el entorno de llamada.

Si queremos usar un símbolo del entorno de llamada, querremos que un símbolo sea opaco. Usualmente este símbolo no deberá ser pasado por argumento porque es posible que ni siquiera exista (caso Windows/Linux).

Esto es exactamente lo mismo que hacemos con funciones. La salvedad es que en las funciones trabajamos con valores (en tiempo de ejecución) mientras que en macros trabajamos con símbolos (en tiempo de compilación). Obviamente, no existe esta distinción en lenguajes homoicónicos como LISP donde la compilación y la ejecución van a la par.

Traducción

Esto significa que existen los mismos conceptos de higiene y transparencia referencial en las funciones y, además, existen unos motivos muy parecidos para tener excepciones a la regla.

Por ejemplo:

En general queremos proteger los símbolos. Una macro debe ser higiénica y transparente por defecto.

En general queremos proteger los valores. Una función debe ser higiénica y transparente por defecto.

Realmente esto es cierto, aunque es muy fácil perder la transparencia en lenguajes como el C/C++. Lo veremos más abajo.

Si queremos definir un símbolo en el entorno de llamada, querremos que un símbolo sea no-higiénico. Usualmente este símbolo deberá ser pasado por argumento para controlar qué se ensucia en el entorno de llamada.

Si queremos modificar un valor en el entorno de llamada, querremos que un valor sea no-higiénico. Usualmente este valor deberá ser pasado por referencia para controlar qué se modifica en el entorno de llamada.

Así pues, opino que existe una analogía entre la higiene y el paso por valor. La no-higiene y el paso por referencia.

Si queremos usar un símbolo del entorno de llamada, querremos que un símbolo sea opaco. Usualmente este símbolo no deberá ser pasado por argumento porque es posible que ni siquiera exista (caso Windows/Linux).

Si queremos usar un valor del entorno de llamada, querremos que ese valor sea accesible. Usualmente este valor no deberá ser pasado por argumento porque es posible que ya podamos acceder a él.

El ejemplo claro es una variable global. Al ser global está en el entorno de llamada. Además, ya podemos acceder a ella por lo que no necesitamos pasarla por argumento. De hecho, es esto lo que hace que la función no sea transparente. Depende de algo que no pasamos por argumentos. Esto es muy común en C/C++ donde hay variables globales, estáticas y argumentos implícitos.

0 comentarios:

Publicar un comentario en la entrada