Caracteristicas avanzadas de LISP





 Entre las características del LISP, la facilidad de definición de macro y las funciones «eval», «mapcar», «mapcan» y «apply» son, quizá, las más importantes.

Definición y expansión de macros

La noción de «macro», en general, es la de que una función puede automáticamente reinstanciarse o «generarse» en línea dentro del texto de un programa siempre que se necesite. Las macros han sido una importante herramienta de los programadores de sistemas durante mucho tiempo, pero su potencia se ha utilizado principalmente a nivel del lenguaje ensamblador.

En  LISP,  las  macros  ofrecen  una  alternativa  a  las funciones para el mismo propósito. Una definición de macro en LISP tiene la siguiente forma básica:

 (defun nombre macro (parámetro) e1 e2 … en)

 (Algunas implementaciones requieren una sintaxis alga diferente a ésta, usando «dm» para la definición de macro en vez de «defun» y «macro». El lector debe ser capaz de asimilar estas diferencias  sintácticas.) «Nombre» identifica a la macro y «parámetro» es un valor que será sustituido en las expresiones e1, e2, … y en cuando se expanda la macro. El resultado de la expansión se ejecuta entonces en línea.

Una macro se llama igual que si fuera una función:

 (nombre argumentos)

 

Pero la acción que tiene lugar no es una transferencia de control, como con las funciones, sino una generación en línea de texto del programa, el cual se ejecuta a continuación.

Para ilustrar esto, supongamos que queremos definir una macro que simule una sentencia while de otro lenguaje; esto es,

(while X Y)

 

ejecutaría repetidamente Y hasta que X se hace 0. La «forma» de este bucle será como sigue:

 

(prog ()

bucle (cond ((greaterp X 0)

(Y

(setq X (subl X))

(go bucle)))))

 

Esto es, si X > 0 entonces se ejecuta Y, se decrementa X en 1 y se repite el bucle.

Puede definirse entonces una macro llamada «while» con la anterior configuración como su cuerpo y representando el parámetro P toda la llamada a la macro (while X Y), como sigue:

 

(defun while macro (P) (subst (cadr P) ‘X) ( subst (caddr P) ‘Y) (prog ()

bucle (cond ((greaterp X 0) (Y (

setq X (subl X)) (go bucle)))))

 

Las dos funciones «subst» reemplazan al primer  y segundo argumento de la llamada para X en el cuerpo de la definición de la macro y luego se ejecuta el cuerpo. Por ejemplo, la siguiente llamada a macro repite el cálculo del factorial F de N, mientras el valor de I es mayor que 0.

 

(while I (setq F (* F D))





 

La expansión de esta llamada a macro, cuando es ejecutada, aparece a continuación

 

(prog ()

bucle (cond ((greaterp I 0)

((setq F (* F b) (setq I (subl b) (go bucle)))))

Observe que (cadr P) es I en este caso y (caddr P) es (setq F (* F D). Este código puede compararse con la versión iterativa de la función factorial presentada anteriormente.

 

 

Eval, Mapcar Y Aaply

La macro es un dispositivo para la suspensión temporal de la ejecución de un programa, mientras se generan o transforman automáticamente ciertas sentencias del programa. Lo mismo puede hacerse de una forma más modesta usando la función «eval».

Eval es la función opuesta de «quote», en el siguiente sentido. Si una variable X tiene el valor (A B), entonces la expresión

 

(list X ‘C)

 

da el resultado (A B C). Sin embargo, la expresión (list ‘X ‘C) fuerza a que X se trate como un literal sin valor, en vez de como una variable, por lo que el resultado es (X C).

Cuando  se  aplica  eval  a  una  expresión  con  comilla, anula el efecto de la comilla y fuerza a que se evalúe la expresión. Por tanto, continuando con el ejemplo anterior:

 

(list (eval ‘X) ‘C)

 

da de nuevo el resultado (A B C), puesto que (eval ‘X) es equivalente a la expresión X en este contexto.

 

 

La función «mapcar» tiene la siguiente forma general:

 

(mapcar ‘nombre ‘args)

 

«Nombre» es el nombre de alguna función y «args» es una lista de argumentos para los cuales y en orden debe aplicarse repetidamente la función especificada.

Por ejemplo:

(mapcar ‘subl ‘(1 2 3))

 

da la expresión resultante:

 

((subl 1) (subl 2) (subl 3))

 

Esto es, la función es copiada para los elementos de la lista, dando como resultado una lista de aplicaciones de la misma función a diferentes argumentos.

La función «apply» se utiliza para que se aplique repetidamente una función a una lista de argumentos, en vez de sólo una vez a los distintos argumentos requeridos por la función. Su forma general es:

 

(apply función (argumentos))

 

Por ejemplo, supongamos que queremos calcular la suma de los elementos de la lista ( 1 2 3). Podemos hacer esto escribiendo

 

(apply ‘ + (I 2 3))

 

lo cual es equivalente a la evaluación anidada (+ (+ 1 2) 3). Observe que

 

(+ (1 2 3))

 

no funcionaría, puesto que «+» es estrictamente una función de argumentos numéricos.





También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *