LECCION 4. FUNCIONES (II). En esta lección se aplican las técnicas y los recursos expuestos en las lecciones anteriores. En primer lugar, se profundiza en las técnicas de programación. Por otra parte, se muestra cómo es posible simular el paso de mensajes y las funciones genéricas mediante cierres léxicos. “LAMBDA, el GOTO definitivo” (Guy L. Steele, jr.) Inteligencia Artificial e I.C.. 2002/03 4.1 Dpto. Leng. Ciencias Comp. Inteligencia Artificial e I.C.. 2002/03 4.2 Dpto. Leng. Ciencias Comp. R.4.1. Filtrado de listas (I) Definir las siguientes funciones: a) Mi-remove-if y mi-remove-if-not, que tienen dos argumentos: un predicado p (de un argumento) y una lista L. Mi-remove-if devuelve una lista formada por los elementos de L que no satisfacen p. Mi-remove-if-not devuelve una lista formada por los elementos de L que satisfacen p. b) Mi-substitute-if, que tiene tres argumentos: una expresión e, un predicado p (de un argumento) y una lista L. Mi-substitute-if devuelve una lista formada por los mismos elementos que L, salvo los que satisfacen p, que son sustituidos por e. c) Mi-some y mi-every, que tienen dos argumentos: un predicado p (de un argumento) y una lista L. Mi-some devuelve T si algún elemento de ,L satisface p, NIL en otro caso. Mi-every devuelve T si todos los elementos de L satisfacen p, NIL en otro caso. d) Mi-find-if, que tiene dos argumentos: un predicado p (de un argumento) y una lista L. Mi-find-if devuelve el primer elemento de L que satisface p, o NIL si ninguno lo satisface. ************************** SOLUCION: a) Podemos dar una definición recursiva directa: si L es NIL, el valor es NIL; en otro caso, si car(L) satisface p, el valor es el resultado de aplicar la función sobre cdr(L); en otro caso, el valor es el resultante de CONSar car(L) con el resultado de aplicar la función sobre cdr(L). En Lisp (DEFUN MI-REMOVE-IF (P L) (COND ((NULL L) NIL) ((FUNCALL P (CAR L)) (MI-REMOVE-IF P (CDR L))) (T (CONS (CAR L) (MI-REMOVE-IF P (CDR L)))))) De MI-REMOVE-IF-NOT también podemos dar una definición directa; pero, ¿para qué escribir tanto? Definamos la función inversa-booleana: (DEFUN INVERSA-BOOLEANA (P) #'(LAMBDA (X) (NOT (FUNCALL P X)))) y será simplemente (DEFUN MI-REMOVE-IF-NOT (P L) (MI-REMOVE-IF (INVERSA-BOOLEANA P) L)) b) Como antes, podemos dar una definición recursiva directa; pero anora la daremos empleando MAPCAR. Para cada elemento en de L devolvemos e o bien el mismo en, según satisfaga o no el predicado p. En Lisp (DEFUN MI-SUBSTITUTE-IF (E P L) (MAPCAR #'(LAMBDA (X) (IF (FUNCALL P X) E X)) L)) c) Análogamente (DEFUN MI-SOME (P L) (COND ((NULL L) NIL) ((FUNCALL P (CAR L)) T) (T (MI-SOME P (CDR L))))) y (DEFUN MI-EVERY (P L) (COND ((NULL L) T) ((FUNCALL P (CAR L)) (MI-EVERY P (CDR L))) (T NIL))) o bien (DEFUN MI-EVERY (P L) (NOT (MI-SOME (INVERSA-BOOLEANA P) L))) d) Por último (DEFUN MI-FIND-IF (P L) (COND ((NULL L) NIL) ((FUNCALL P (CAR L)) (CAR L)) (T (MI-FIND-IF P (CDR L))))) NOTA. Todas estas funciones están predefinidas en Common Lisp. Su definición es más general, pues no sólo se aplican a listas, sino a sucesiones (listas, vectores y cadenas). NOTA. Todas estas funciones tienen un "aire de familia"; es posible abstraer un grado más y definirlas como instancias de una función de reducción o plegado (vd. R.4.3) Inteligencia Artificial e I.C.. 2002/03 4.3 Dpto. Leng. Ciencias Comp. R.4.2. Filtrado de listas (II). a) Definir en Lisp la función substitute-if-2, que tiene tres argumentos: un predicado binario p, una función binaria f y una lista L. Substitute-if-2 devuelve una lista formada a partir de L suprimiendo el primer par de elementos consecutivos e, e’ de L tales que satisfacen p(e, e’), y sustituyéndolos por f(e, e’). Si no existe tal par, se devuelve la misma L. Por ejemplo (SUBSTITUTE-IF-2 #'< #'+ '(6 4 2 3 10 8)) => (6 4 5 10 8) (SUBSTITUTE-IF-2 #'= #'+ '(6 4 2 3 10 8)) => (6 4 2 3 10 8) b) Definir en Lisp la función substitute-if-n, que tiene tres argumentos: un predicado p (de dos argumentos), una función binaria f y una lista L. Substitute-if-n devuelve una lista calculada aplicando sucesivamente substitute-if-2, hasta que se alcance un valor fijo. c) La sucesión de Hilgemeier {hi} es una sucesión de listas de enteros dada por (1) es decir, un uno h0 = (1 1) es decir, dos unos h1 = h2 = (2 1) es decir, un dos un uno h3 = (1 2 1 1) es decir, un uno un dos dos unos h4 = (1 1 1 2 2 1) ... hi+1 = la descripción de hi escrita como lista de números. Definir la función HILGE(n), que devuelve el n-ésimo término de la sucesión de Hilgemeier. ************************** SOLUCION: a)Si L esta vacía o consta de un solo valor es L; en otro caso, si los dos primeros elementos satisfacen p, se devuelve la lista formada CONSando f(car(L), cadr(L)) y cdr(L); en otro caso se recurre sobre cdr(L). En Lisp (DEFUN SUBSTITUTE-IF-2 (P F L) (COND ((NULL L) NIL) ((NULL (CDR L)) L) ((FUNCALL P (CAR L) (CADR L)) (CONS (FUNCALL F (CAR L) (CADR L)) (CDDR L))) (T (CONS (CAR L) (SUBSTITUTE-IF-2 P F (CDR L)))))) b) Lo que se está definiendo es la función de punto fijo correspondiente a SUBSTITUTE-IF-2. Definamos la función "punto fijo", que tiene como argumentos una función f y una expresión prueba, y devuelve el primer valor de la sucesión {ei }dada por e0 =prueba, ei+1 =f(ei) tal que ei+1=ei: (DEFUN PUNTO-FIJO (F PRUEBA) (COND ((EQUAL PRUEBA (FUNCALL F PRUEBA)) PRUEBA) (T (PUNTO-FIJO F (FUNCALL F PRUEBA))))) Para no llamar dos veces a F, podemos introducir una función auxiliar: (DEFUN PUNTO-FIJO (F PRIMERA-PRUEBA) (PUNTO-FIJO-AUX F PRIMERA-PRUEBA (FUNCALL F PRIMERA-PRUEBA))) (DEFUN PUNTO-FIJO-AUX (F S FS) (COND ((EQUAL S FS) S) (T (PUNTO-FIJO-AUX F FS (FUNCALL F FS))))) Y aún podemos mejorar esta definición, considerando que el predicado de igualdad se puede pasar como argumento a PUNTO-FIJO: (DEFUN PUNTO-FIJO (F PRIMERA-PRUEBA P) (PUNTO-FIJO-AUX F PRIMERA-PRUEBA (FUNCALL F PRIMERA-PRUEBA) P)) (DEFUN PUNTO-FIJO-AUX (F S FS P) (COND ((FUNCALL P S FS) S) (T (PUNTO-FIJO-AUX F FS (FUNCALL F FS) P)))) Ahora SUBSTITUTE-IF-N será simplemente (DEFUN SUBSTITUTE-IF-N (PRED F LISTA) (PUNTO-FIJO #'(LAMBDA (L) (SUSBSTITUTE-IF-2 PRED F L)) LISTA)) Inteligencia Artificial e I.C.. 2002/03 4.4 Dpto. Leng. Ciencias Comp. El punto fijo se alcanza en un número finito de pasos: en efecto, (REPLACE-IF-2 P L) devuelve o bien L, en cuyo caso ya se ha llegado al punto fijo, o bien una lista de longitud inferior en una unidad, lo cual sólo puede ocurrir un número finito de veces. c) La definición recursiva es fácil, supuesta definida sig-hilge que calcula el siguiente elemento de la sucesión: (DEFUN HILGE (N) (COND ((ZEROP N) (LIST 1)) ( T (SIG-HILGE (HILGE (1- N)))))) El valor de sig-hilge(L) puede calcularse de muchas formas. La que proponemos aquí es elegante (aunque no necesariamente eficiente): 1) contemos una vez cada elemento de L, creando así una lista de listas L’. Por ejemplo, si L es (1 1 1 2 2 1) L’ será ((1 1) (1 1) (1 1) (1 2) (1 2) (1 1)) Ello equivale a calcular la lista L’, formada a partir de L LISTando cada uno de sus elementos y el número 1. Es decir, L’ es el resultado de aplicar #'(LAMBDA (X) (LIST 1 X)) a cada elemento de L, o sea, L’ es el resultado de (MAPCAR #'(LAMBDA (X) (LIST 1 X)) L). Por ejemplo, si L es (1 1 1 2 2 1) L’ será ((1 1) (1 1) (1 1) (1 2) (1 2) (1 1)) 2) si dos cuentas consecutivas se refieren al mismo valor, debemos acumularlas en una sola cuenta. Por ejemplo, si L’ es ((1 1) (1 1) (1 1) (1 2) (1 2) (1 1)) debemos quedarnos con ((2 1) (1 1) (1 2) (1 2) (1 1)), ((3 1) (1 2) (1 2) (1 1)) y finalmente con ((3 1) (2 2) (1 1)) Ello equivale a aplicar a L’ el proceso REPLACE-IF-N con predicado #'(LAMBDA (L1 L2) (= (CADR L1) (CADR L2))) y función de reemplazamiento #'(LAMBDA (L1 L2) (LIST (+ (CAR L1) (CAR L2)) (CADR L1))) 3) Formemos una sola lista con los pares que finalmente hayan quedado. Es decir, APPLYamos #'APPEND al resultado anterior. En Lisp (DEFUN SIG-HILGE (L) (APPLY #'APPEND (REPLACE-IF-N #'(LAMBDA (L1 L2) (= (CADR L1) (CADR L2))) #'(LAMBDA (L1 L2) (LIST (+ (CAR L1) (CAR L2)) (CADR L1))) (MAPCAR #'(LAMBDA (X) (LIST 1 X)) L)))) Inteligencia Artificial e I.C.. 2002/03 4.5 Dpto. Leng. Ciencias Comp. R.4.6. Programación por paso de mensajes. Deseamos diseñar un programa para representar y manejar cuadrados y triángulos equiláteros, definidos ambos por las coordenadas de su centro y la longitud de su lado. El programa debe ser capaz de calcular las áreas y los perímetros de estas figuras. a)Definir una implementación Lisp basada en el paso de mensajes, en la que los objetos se representen como cierres léxicos. b)En esta implementación, trazar la evaluación de (PERIMETRO (HACER CUADRADO 210 120 1)) c)Modificar la implementación para tratar también los círculos, definidos por su centro y radio. d)Modificar la implementación para calcular también los diámetros de los objetos. Se entiende por diámetro de un polígono la longitud del mayor segmento que puede trazarse en el interior del polígono: para el cuadrado es la diagonal y para el triángulo equilátero el lado. ************************** SOLUCION: a)En R.2.8 representábamos los objetos mediante listas, y las operaciones sobre los objetos mediante un conjunto de funciones independientes de estas listas. En la representación basada en cierres léxicos se adopta un punto de vista radicalmente opuesto: cada objeto se encarga de definir sus propias funciones. Los constructores son por tanto más complejos: (DEFUN HACER-TRIANGULO (X Y L) #'(LAMBDA (MSJ) (CASE MSJ (LADO L) (CENTROX X) (CENTROY Y) (ALTURA (* 0.5 (SQRT 3) L)) (AREA (* 0.5 L (* 0.5 (SQRT 3) L))) (PERIMETRO (* 3 L))))) (DEFUN HACER-CUADRADO (X Y L) #'(LAMBDA (MSJ) (CASE MSJ (LADO L) (CENTROX X) (CENTROY Y) (ALTURA L) (AREA (* L L)) (PERIMETRO (* 4 L))))) Por el contrario, las funciones son muy sencillas. Definimos un aplicador genérico (DEFUN OPERAR (MSJ OBJ) (FUNCALL OBJ MSJ)) Y, si lo deseamos, podemos dar nombres a las operaciones especificadas: (DEFUN LADO (OBJ) (OPERAR ´LADO OBJ)) (DEFUN CENTROX (OBJ) (OPERAR 'CENTROX OBJ)) (DEFUN CENTROY (OBJ) (OPERAR 'CENTROY OBJ)) (DEFUN ALTURA (OBJ) (OPERAR 'ALTURA OBJ)) (DEFUN AREA (OBJ) (OPERAR 'AREA OBJ)) (DEFUN PERIMETRO (OBJ) (OPERAR 'PERIMETRO OBJ)) b) Evaluemos el argumento (HACER-CUADRADO 210 120 1) => X <- 210 Y <- 120 L <- 1 #'(LAMBDA (MSJ) (CASE MSJ (LADO) L) (CENTROX X) (CENTROY Y) (ALTURA L) (AREA (* L L)) (PERIMETRO (* 4 L)))) Inteligencia Artificial e I.C.. 2002/03 4.6 Dpto. Leng. Ciencias Comp. Llamemos C1 a este cierre léxico. Ahora se puede evaluar la expresión propuesta: (PERIMETRO (HACER-CUADRADO 210 120 1)) == OBJ <- C1 (OPERAR 'PERIMETRO OBJ) == OBJ <- C1 MSJ <- PERIMETRO (FUNCALL OBJ MSJ) == (* 4 1) => 4 c)Es necesario añadir un constructor de círculos: (DEFUN HACER-CIRCULO (X Y R) #'(LAMBDA (MSJ) (CASE MSJ (RADIO R) (CENTROX X) (CENTROY Y) (AREA (* PI R R)) (PERIMETRO (* 2 PI R))))) y añadir la nueva función RADIO: (DEFUN RADIO (OBJ) (OPERAR ´RADIO OBJ)) El resto permanece igual. d)Es necesario modificar todos los constructores: (DEFUN HACER-TRIANGULO (X Y L) #'(LAMBDA (MSJ) (CASE MSJ (LADO L) (CENTROX X) (CENTROY Y) (ALTURA (* 0.5 (SQRT 3) X)) (AREA (* 0.5 L (* 0.5 (SQRT 3) X))) (PERIMETRO (* 3 L)) (DIAMETRO L)))) (DEFUN HACER-CUADRADO (X Y L) #'(LAMBDA (MSJ) (CASE MSJ (LADO L) (CENTROX X) (CENTROY Y) (ALTURA L) (AREA (* L L)) (PERIMETRO (* 4 L)) (DIAMETRO (* (SQRT 2) L))))) (DEFUN HACER-CIRCULO (X Y R) #'(LAMBDA (MSJ) (CASE MSJ (RADIO R) (CENTROX X) (CENTROY Y) (AREA (* PI R R)) (PERIMETRO) (* 2 PI R)) (DIAMETRO (* 2 R))))) y añadir la nueva función DIAMETRO: (DEFUN DIAMETRO (OBJ) (OPERAR ´DIAMETRO OBJ)) Inteligencia Artificial e I.C.. 2002/03 4.7 Dpto. Leng. Ciencias Comp. R.4.7. Programación dirigida por los datos. Diseñar una implementación alternativa para los apartados a), b), c) de R.4.6, en la que los objetos se representen por listas y exista un operador genérico OPERAR; la manera de efectuar las operaciones será mediante llamadas (OPERAR operación objeto) ************************** SOLUCION: a)Podemos emplear los mismos constructores y predicados de tipo que en R.2.8: (DEFUN HACER-TRIANGULO (X Y L) (LIST 'TRIANGULO X Y L)) (DEFUN HACER-CUADRADO (X Y L) (LIST 'CUADRADO X Y L)) (DEFUN TIPO (OBJ) (CAR OBJ)) (DEFUN TRIANGULO-P (OBJ) (EQ (TIPO OBJ) 'TRIANGULO)) (DEFUN CUADRADO-P (OBJ) (EQ (TIPO OBJ) 'CUADRADO)) Sin embargo, las funciones deben implementarse de otra forma para permitir la definición de OPERAR. Definiremos una pequeña función anónima para cada operación sobre cada tipo de objeto; por ejemplo, el lado del cuadrado será (LAMBDA (OBJ) (CADDDR OBJ)) El perímetro del cuadrado será (LAMBDA (OBJ) (* 4 (CADDDR OBJ))) y análogamente los demás casos. Todas estas funciones anónimas se ponen en correspondencia con los tipos mediante una tabla, que para cada tipo y nombre de operación devuelve la función que corresponde: (DEFUN TABLA (OPERACION TIPO) (CASE TIPO (TRIANGULO (CASE OPERACION (LADO #'(LAMBDA (OBJ) (CADDDR OBJ))) (CENTROX #'(LAMBDA (OBJ) (CADR OBJ))) (CENTROY #'(LAMBDA (OBJ) (CADDR OBJ))) (ALTURA #'(LAMBDA (OBJ) (* 0.5 (SQRT 3) (OPERAR 'LADO OBJ)))) (AREA #'(LAMBDA (OBJ) (* 0.5 (OPERAR 'LADO OBJ) (OPERAR 'ALTURA OBJ)))) (PERIMETRO #'(LAMBDA (OBJ) (* 3 (OPERAR 'LADO OBJ)))))) (CUADRADO (CASE OPERACION (LADO #'(LAMBDA (OBJ) (CADDDR OBJ))) (CENTROX #'(LAMBDA (OBJ) (CADR OBJ))) (CENTROY #'(LAMBDA (OBJ) (CADDR OBJ))) (ALTURA #'(LAMBDA (OBJ) (OPERAR 'LADO OBJ))) (AREA #'(LAMBDA (OBJ) (* (OPERAR 'LADO OBJ) (OPERAR 'ALTURA OBJ)))) (PERIMETRO #'(LAMBDA (OBJ) (* 4 (OPERAR 'LADO OBJ)))))))) La función OPERAR genérica será simplemente (DEFUN OPERAR (OPERACION OBJ) (FUNCALL (TABLA OPERACION (TIPO OBJ)) OBJ)) c )Añadimos el constructor de círculos: (DEFUN HACER-CIRCULO (X Y R) (LIST ´CIRCULO X Y R)) (DEFUN CIRCULO-P (OBJ) (EQ (TIPO OBJ) ´CIRCULO)) Consideramos las funciones elementales necesarias: por ejemplo, para el radio (LAMBDA (OBJ) (CADDDR OBJ)) Para el área (LAMBDA (OBJ) (* PI (OPERAR 'RADIO OBJ) (OPERAR 'RADIO OBJ))) Inteligencia Artificial e I.C.. 2002/03 4.8 Dpto. Leng. Ciencias Comp. Y para el perímetro (LAMBDA (OBJ) (* 2 PI (OPERAR 'RADIO OBJ))) Y las insertamos en la tabla: (DEFUN TABLA (OPERACION TIPO) (CASE TIPO (CIRCULO (CASE OPERACION (RADIO #'(LAMBDA (OBJ) (CADDDR OBJ))) (CENTROX #'(LAMBDA (OBJ) (CADR OBJ))) (CENTROY #'(LAMBDA (OBJ) (CADDR OBJ))) (ALTURA #'(LAMBDA (OBJ) (* 0.5 (SQRT 3) (OPERAR 'LADO OBJ)))) (AREA #'(LAMBDA (OBJ) (* PI (OPERAR 'RADIO OBJ) (OPERAR 'RADIO OBJ)))) (PERIMETRO #'(LAMBDA (OBJ) (* 2 PI (OPERAR 'RADIO OBJ)))))) (TRIANGULO (CASE OPERACION (LADO #'(LAMBDA (OBJ) (CADDDR OBJ))) (CENTROX #'(LAMBDA (OBJ) (CADR OBJ))) (CENTROY #'(LAMBDA (OBJ) (CADDR OBJ))) (ALTURA #'(LAMBDA (OBJ) (* 0.5 (SQRT 3) (OPERAR 'LADO OBJ)))) (AREA #'(LAMBDA (OBJ) (* 0.5 (OPERAR 'LADO OBJ) (OPERAR 'ALTURA OBJ)))) (PERIMETRO #'(LAMBDA (OBJ) (* 3 (OPERAR 'LADO OBJ)))))) (CUADRADO (CASE OPERACION (LADO #'(LAMBDA (OBJ) (CADDDR OBJ))) (CENTROX #'(LAMBDA (OBJ) (CADR OBJ))) (CENTROY #'(LAMBDA (OBJ) (CADDR OBJ))) (ALTURA #'(LAMBDA (OBJ) (OPERAR 'LADO OBJ))) (AREA #'(LAMBDA (OBJ) (* (OPERAR 'LADO OBJ) (OPERAR 'ALTURA OBJ)))) (PERIMETRO #'(LAMBDA (OBJ) (* 4 (OPERAR 'LADO OBJ)))))))) d) Añadimos las operaciones elementales necesarias: Para el diámetro del círculo: (LAMBDA (OBJ) (* 2 (RADIO OBJ))) Para el diámetro del cuadrado: (LAMBDA (OBJ) (* (SQRT 2) (LADO OBJ))) y las insertamos en la tabla: Modificamos la tabla, insertando estas nuevas funciones: (DEFUN TABLA (OPERACION TIPO) (CASE TIPO (CIRCULO (CASE OPERACION (DIAMETRO #'(LAMBDA (OBJ) (* 2 (RADIO OBJ))) ... ...)) (TRIANGULO (CASE OPERACION (DIAMETRO #'(LAMBDA (OBJ) (CADDDR OBJ))) ... ...)) (CUADRADO (CASE OPERACION (DIAMETRO #'(LAMBDA (OBJ) (* (SQRT 2) (LADO OBJ)))) ... ...)))) Inteligencia Artificial e I.C.. 2002/03 4.9 Dpto. Leng. Ciencias Comp. EJERCICIOS PROPUESTOS. P.4.1. Definir las siguientes funciones: a) Remove-if-tree, que tiene como argumentos un predicado unitario p y una lista con anidamientos L, y devuelve la lista formada suprimiendo en L aquellos átomos que satisfacen p. Por ejemplo, si p es ZEROP y L es ((3 0) (4 (0 0))), se devuelve ((3) (4 ())). b) Replace-if-tree, que tiene como argumentos un predicado unitario p, una función f y una lista con anidamientos L, y devuelve la lista formada sustituyendo en L cada átomo x que satisface p por f(x). Por ejemplo, si p es ZEROP, f es la función sucesor y L es ((3 0) (4 (0 0))), se devuelve ((3 1) (4 (1 1))) P.4.2. a) Definir una función Lisp de argumento k que compruebe para todos los valores naturales menores que k la validez del siguiente enunciado: “No existen números naturales x, y, z tales que 3 3 3 x +y =z” b)Definir la función Lisp (CRIBA N), que devuelve la sucesión de todos los números primos hasta N empleando la criba de Eratóstenes. P.4.3. La sucesión de Ulam {Ui} se define como sigue: {Ui} es una sucesión creciente de números tal naturales tal que U1 = 1 U2 = 2 y para todo n∈N, n aparece en la sucesión si y sólo si n se puede expresar de manera única como suma de dos elementos anteriores de la sucesión. Definir la función Lisp (ULAM N) que devuelve los elementos de la sucesión de Ulam comprendidos entre 1 y N. P.4.4. Supongamos dos funciones f y g de la misma aridad n que devuelven valores naturales. Se dice que f y g son extensionalmente iguales cuando para toda n-tupla (a1, ..., an), f(a1, ..., an) = g(a1, ..., an). ¿Es posible implementar una función EQUAL-F que tenga como argumentos dos funciones y devuelva “verdadero” cuando ambas funciones sean extensionalmente iguales, “falso” en otro caso? P.4.6. Deseamos diseñar un programa para representar y manejar cubos y tetraedros, definidos ambos por las coordenadas de su centro y la longitud de su arista. El programa debe ser capaz de calcular los volúmenes y las superficies de estas figuras. a)Definir una implementación Lisp basada en el paso de mensajes, en la que los objetos se representen como cierres léxicos. b) Modificar la implementación dada en a) para representar también las esferas. Cada esfera se identifica por su radio y las coordenadas de su centro. P.4.7. Repetir el ejercicio P.4.6, empleando esta vez el paradigma de programación basada en el paso de mensajes. Inteligencia Artificial e I.C.. 2002/03 4.10 Dpto. Leng. Ciencias Comp. NOTAS ERUDITAS Y CURIOSAS. Las técnicas de filtrado son características de la programación funcional. Sin embargo, hay que señalar que su uso efectivo exige el empleo de la llamada evaluación “perezosa” y de las corrientes o “streams”. La asignación de un significado funcional f a un símbolo s con DEFUN permite definir f de manera recursiva, empleando el nombre s en el cuerpo de su misma definición. Pero, como señala McCarthy (McCarthy, 1981), parecía deseable que la notación empleada para denotar argumentos funcionales explícitos -sin un DEFUN previo- fuera capaz de representar la recursividad. Una primera solución para ello -propuesta por Nataniel Rochester- fue hacer que las funciones anónimas dejaran de serlo, mediante la forma LABEL. De esta manera, se podían pasar argumentos funcionales recursivos como por ejemplo (la sintaxis actual es algo diferente, vd. lección 5) Figura IV.1. Harold Abelson. (LABEL PEPE (LAMBDA (L) (COND ((NULL L NIL) (T (PEPE (CDR L))))) Sin embargo, David Park (1935-1990) -entonces un alumno del MIT, enseguida uno de los “padres” de la Informática Teórica- señaló que desde el punto de vista lógico la construcción anterior era innecesaria, ya que algo parecido al combinador Y del lambda-cálculo podía representar el mismo papel. En el lambda cálculo, se demuestra la existencia de una expresión Y tal que para toda expresión E, (Y)E => (E)(Y)E => (E)(E)(Y)E => ... => (E)...(E)(Y)E. Esta expresión Y es λy.(λx.(y)(x)x)λx.(y)(x)x Ahora bien, toda definición recursiva de una función de orden superior E implica una ecuación de punto fijo de la forma X = (E) X Nótese que, sustituyendo X por (Y)E queda (Y)E = (E) (Y)E que, como hemos dicho, es una propiedad del combinador Figura IV.2. David Park en 1960. Y. Por tanto, el combinador Y permite prescindir de la recursión. Las técnicas de “programación por paso de mensajes” y “programación dirigida por los datos” han sido expuestas con claridad difícilmente superable por Abelson y Sussman en SICP (Abelson y Sussman 85). El modelo de paso de mensajes es el que subyace en los lenguajes convencionales de programación orientada a objetos; el modelo de programación dirigida por los datos es el que subyace en CLOS (Common Lisp Object System) Inteligencia Artificial e I.C.. 2002/03 4.11 Dpto. Leng. Ciencias Comp.