leccion 3. funciones - Departamento de Lenguajes y Ciencias de la

Anuncio
LECCION 3. FUNCIONES (I).
En esta lección se dan los primeros pasos para emplear Common Lisp como lenguaje de
programación funcional. Al finalizar la lección, el alumno debe ser capaz de
-manejar la notación lambda y la correspondiente notación Lisp (ejercicios1-4).
-recuperar explícitamente objetos-procedimiento, y ligar símbolos a ellos (ejercicios 2 y 8).
-emplear objetos-procedimiento como argumento de funciones (ejercicios 3 y sigs.).
-definir funciones que devuelven objetos-procedimiento (ejercicio 10).
-emplear las funciones MAP para procesar listas (ejercicios 6, 7 y 9).
-manejar cierres léxicos (ejercicios 8 y sigs.).
“El décimo mandamiento: abstraer las funciones
de estructura común, definiendo una sola función.”
(The Little LISPer)
Inteligencia Artificial e I.C.. 2004/05
3.1
Dpto. Leng. Ciencias Comp.
Inteligencia Artificial e I.C.. 2004/05
3.2
Dpto. Leng. Ciencias Comp.
R.3.1. Expresiones lambda.
Evaluar las siguientes expresiones:
a)
((LAMBDA (X) (+ X 1)) 7)
b)
((LAMBDA NIL 7 8 9))
c)
((LAMBDA (L1 L2)
(LIST (CAR L1) (CAR L2)))
'(ALONSO ALONZO)
'(ALFONSO))
d)
((LAMBDA (X) (APPEND X X))
((LAMBDA (X) (LIST X X)) 'CHURCH))
e)
((LAMBDA (L1)
((LAMBDA (L2)
(LIST (CAR L1) (CAR L2)))
'(ALONSO ALONZO)))
'(ALFONSO))
f)
('(LAMBDA (X) (+ X 1)) 7)
**************************
SOLUCION:
Una expresión lambda es una lista de la forma
(LAMBDA lista-lambda [expresión]*)
donde lista-lambda supondremos por ahora que es una lista de símbolos (parámetros). Nótese la
similitud sintáctica de una expresión lambda con una forma DEFUN.
Las expresiones lambda sirven para referirse a funciones sin necesidad de darles nombre.
Una expresión lambda da directamente la definición de una función. Así, por ejemplo, la expresión
(LAMBDA (X) (+ X X))
es la definición de la función duplo, y se puede leer simplemente como "la función de x que
devuelve x+x". Las expresiones lambda están inspiradas en la notación del lambda-cálculo, en la
que la función anterior se expresaría como
λx.x+x
Una expresión lambda puede aparecer en los mismos lugares que un símbolo con significado
funcional. Por ejemplo, puede aparecer como primer elemento de una lista que se ha de evaluar;
se dice entonces que tenemos una forma lambda. Los restantes elementos de la lista son los
argumentos que se pasan a la definición lambda: estos argumentos sustituyen a los parámetros en
[expresión]* y se devuelve el valor de la última de ellas. Por tanto, para considerar las formas
lambda la regla de evaluación de listas dada en R.1.1 debe completarse de la siguiente manera:
1. Si el primer elemento de una lista es una expresión lambda, se considera el objetoprocedimiento F definido por la expresión.
2. Se evalúan los restantes elementos de la lista, obteniendo los valores V1, ..., Vn. Si el
número o tipo de los valores obtenidos no es coherente con los argumentos requeridos por F, se
produce error.
3. La lista se evalúa a F(V1, ..., Vn).
Ya podemos resolver los apartados a)-e):
a) Es el caso más sencillo:
((LAMBDA (X) (+ X 1)) 7)
==
X <- 7
(+ X 1)
=>8
b) El número de argumentos de la definición puede ser 0:
((LAMBDA NIL 7 8 9))
=>9
c) El número de argumentos puede ser mayor que 1:
Inteligencia Artificial e I.C.. 2004/05
3.3
Dpto. Leng. Ciencias Comp.
((LAMBDA (L1 L2)
(LIST (CAR L1) (CAR L2)))
'(ALONSO ALONZO)
'(ALFONSO))
=>(ALONSO ALFONSO)
d) Para evaluar el argumento de la primera forma lambda, evaluamos otra:
((LAMBDA (X) (APPEND X X))
((LAMBDA (X) (LIST X X)) 'CHURCH))
⇓
(CHURCH CHURCH)
=>(CHURCH CHURCH CHURCH CHURCH)
e) En este caso, el cuerpo de la primera definición contiene una forma lambda:
((LAMBDA (L1)
((LAMBDA (L2)
(LIST (CAR L1) (CAR L2)))
'(ALONSO ALONZO)))
'(ALFONSO))
Se crea un entorno E1 donde L1 está ligado a (ALFONSO)
L1<- (ALFONSO)
y en él se evalúa
((LAMBDA (L2)
(LIST (CAR L1) (CAR L2)))
'(ALONSO ALONZO)))
para lo cual se crea un entorno E2 donde L2 está ligado a (ALONSO ALONZO)
L1 <- (ALFONSO)
L2<- (ALONSO ALONZO)
y en él se evalúa
(LIST (CAR L1) (CAR L2))
que produce finalmente
=> (ALFONSO ALONSO)
El entorno E2 se ha creado dentro del entorno E1, ya que la expresión lambda correspondiente a
E2 aparece sintácticamente dentro de la expresión lambda que origina a E1. Nótese la diferencia
con lo expuesto en R.1.9.c): en aquel caso, el nuevo entorno se creaba fuera del entorno anterior.
Ello se debe a que Common Lisp crea entornos léxicos: el ámbito de la ligadura de una variable
coincide con el ámbito sintáctico en donde está definida esta variable. En el caso de este ejercicio,
la aparición de L1 en (LIST (CAR L1) (CAR L2))) está dentro del par de paréntesis
((LAMBDA (L1) ...) que definen el ámbito donde L1 es una variable.
f) El primer elemento de una forma lambda debe ser simplemente una definición lambda:
('(LAMBDA (X) (+ X 1)) 7)
=> Error: '(LAMBDA (X) (+ X 1)) no es una definición lambda.
Inteligencia Artificial e I.C.. 2004/05
3.4
Dpto. Leng. Ciencias Comp.
R.3.2. Objetos-procedimiento como datos.
Suponiendo evaluada (DEFUN DEF-US (X) (LIST X X X)) y el símbolo JUAN ligado al
símbolo CONS, evaluar las siguientes expresiones:
a)
(FUNCTION CONS)
b)
(FUNCTION 'CONS)
c)
(FUNCTION #'CONS)
d)
#'CONS
e)
#'DEF-US
f)
#'JUAN
g)
#'COND
h)
(FUNCTION (LAMBDA (X) (+ X 1)))
i)
#'(LAMBDA (X) (+ X 1))
j)
(LAMBDA (X) (+ X 1))
k)
(FUNCTION '(LAMBDA (X) (+ X 1)))
l)
#'PEPE
m)
(#'(LAMBDA (X) (+ X 1)) 7)
**************************
SOLUCION:
Hasta ahora hemos considerado en Lisp dos tipos de datos: átomos y listas. Lisp considera
tambien como datos los objetos-procedimiento. Un objeto-procedimiento no debe confundirse con
el símbolo que lo tiene por significado funcional. Por ejemplo, tras ejecutar
(DEFUN F1 (X) (CONS X ´(Y PUNTO)))
existe un objeto-procedimiento -llamémosle F1- que es el significado funcional del símbolo F1 y
cuya definición lambda sería
(LAMBDA (X) (CONS X ´(Y PUNTO)))
El objeto-procedimiento F1 se recuperaría implícitamente al evaluar una lista de la forma (F1
argumento). Hasta ahora esta manera de tratar los objetos-procedimiento, propia de los
lenguajes imperativos, es la única que hemos considerado. Sin embargo, en Lisp es posible
manipular explícitamente un objeto-procedimiento mediante la forma especial FUNCTION:
(FUNCTION argumento)
-un solo argumento, que debe ser un símbolo o una expresión lambda.
-FUNCTION toma literalmente su argumento.
-el valor devuelto es:
-si el argumento es un símbolo, el objeto-procedimiento que es el significado funcional del
símbolo.
-si el argumento es una expresión lambda, el objeto-procedimiento definido por la
expresión.
-es un error llamar a FUNCTION con otro tipo de argumento.
-FUNCTION no puede devover operadores especiales ni macros; por tanto, se produce un
error si el argumento de FUNCTION es un símbolo cuyo significado funcional sea de este tipo.
Un objeto-procedimiento no es algo que se pueda imprimir. Los sistemas Lisp emplean una
notación del tipo de #<función nn> para imprimir el valor devuelto por FUNCTION.
Al igual que para QUOTE, existe una abreviatura para FUNCTION:
(FUNCTION argumento) == #'argumento
Según esto
a)
(FUNCTION CONS)
=> #<función compilada 114>
b)
(FUNCTION 'CONS)
=> Error: (QUOTE CONS) no es un argumento válido.
c)
(FUNCTION #'CONS)
=>Error: (FUNCTION CONS) no es un argumento válido.
d)
#'CONS
=> #<función compilada 114>
Inteligencia Artificial e I.C.. 2004/05
3.5
Dpto. Leng. Ciencias Comp.
e) Los objetos-procedimiento definidos por el programa también son recuperados por FUNCTION:
#'DEF-US
=> #<función de usuario 415>
f) Pero no hay que confundirlos con el valor de una ligadura:
#'JUAN
=> Error: JUAN no tiene significado funcional.
g) Como se ha dicho, se produce un error si el significado funcional de símbolo es una macro o
una forma especial; por tanto
#'COND
=> Error: el significado funcional de COND no es una función.
Recuérdese que AND y OR son macros.
h) Los objetos-procedimiento definidos por una definición lambda también son recuperados por
FUNCTION:
(FUNCTION (LAMBDA (X) (+ X 1)))
=> #<función 21A>
i)
#'(LAMBDA (X) (+ X 1))
=> #<función 23B>
j) ANSI Common Lisp permite realizar una abreviatura adicional; ya que es tan frecuente el uso de
FUNCTION con las definiciones lambda, se permite omitirlo. Dicho de otra forma, cuando el primer
elemento de una forma es LAMBDA, la forma se evalúa como (FUNCTION (LAMBDA ...)). De
esta manera tenemos
(LAMBDA (X) (+ X 1))
=> #<función 23B>
k) Sin embargo...
(FUNCTION '(LAMBDA (X) (+ X 1)))
=> Error: (QUOTE (LAMBDA (X) (+ X 1))) no es un argumento válido
l)
#'PEPE
=> Error: PEPE no tiene significado funcional.
m) Recuérdese que el primer elemento de una forma lambda debe ser una definición lambda:
(#'(LAMBDA (X) (+ X 1)) 7)
=> Error: #'(LAMBDA (X) (+ X 1)) no es una definición lambda.
NOTA: La abreviatura a la que aludimos en el apartado j) no será empleada en el resto de estas
lecciones. Ello se debe a dos razones:
-ha sido introducida en el estándar ANSI; las versiones anteriores de Common Lisp no la permitían.
Por tanto, se señalará un error si se ententa emplear en compiladores o intérpretes anteriores a
1995, y aún en algunos posteriores.
-puede inducir al programador a error, ya que enmascara la diferencia entre nombres de
procedimientos y objetos-procedimiento.
NOTA: En realidad FUNCTION hace algo más que lo explicado aquí: crea si es necesario un cierre
léxico. Vd. R.3.8
NOTA: Los objetos-procedimiento se denominan más frecuentemente "funciones". Preferimos evitar esta
palabra sobrecargada.
Inteligencia Artificial e I.C.. 2004/05
3.6
Dpto. Leng. Ciencias Comp.
R.3.3. Objetos-procedimiento como argumento: FUNCALL.
Suponiendo como en R.3.2. evaluada (DEFUN DEF-US (X) (LIST X X X)) y JUAN ligado a
CONS, y además el símbolo PEPE ligado al resultado de (FUNCTION CONS), evaluar las siguientes
expresiones:
a)
(FUNCALL EXPT 2 3)
b)
(FUNCALL #'EXPT 2 3)
c)
(FUNCALL DEF-US 'LAMBDA)
d)
(DEF-US 'LAMBDA)
e)
(FUNCALL (FUNCTION DEF-US) 'LAMBDA)
f)
(FUNCALL PEPE 'LAMBDA '((X) X))
g)
(FUNCALL #'PEPE 'LAMBDA '((X) X))
h)
(PEPE 'LAMBDA '((X) X))
i)
(JUAN 'LAMBDA '((X) X))
j)
(FUNCALL #'(LAMBDA (X) (* X X)) 7)
k)
(FUNCALL #'AND T NIL T)
l)
(FUNCALL '+ 2 3)
m)
(FUNCALL (QUOTE DEF-US) 'LAMBDA)
n)
(FUNCALL JUAN 'LAMBDA '((X) X))
**************************
SOLUCION:
Existen funciones predefinidas que manejan objetos-procedimiento. Por ejemplo,
FUNCALL:
(FUNCALL arg-funcional [argumento]*)
-FUNCALL es una función propiamente dicha, es decir, evalúa todos sus argumentos.
-el primer argumento debe ser un objeto-procedimiento F.
-los restantes argumentos de FUNCALL arg1, ..., argn deben ser compatibles en número y tipo con
los requeridos por F.
-el valor devuelto es F(arg1, ..., argn).
Recuérdese lo dicho en R.1.8: en CommonLisp la ligadura y el significado funcional de un símbolo
se procesan de manera independiente. Si en la llamada a FUNCALL aparece como argumento
símbolo, se procederá según el ciclo de evaluación Lisp y símbolo se evaluará, es decir, se
buscará su ligadura. En ningún caso se buscará su significado funcional.
Según esto
a)
(FUNCALL EXPT 2 3)
=>Error: EXPT sin ligar.
b)
(FUNCALL #'EXPT 2 3)
=> 8
c)
(FUNCALL DEF-US 'LAMBDA)
=>Error: DEF-US sin ligar.
d)
(DEF-US 'LAMBDA)
=> (LAMBDA LAMBDA LAMBDA)
e)
(FUNCALL (FUNCTION DEF-US) 'LAMBDA)
=> (LAMBDA LAMBDA LAMBDA)
Nótese la equivalencia
(símbolo argumento) == (FUNCALL (FUNCTION símbolo) argumento)
f)
(FUNCALL PEPE 'LAMBDA '((X) X))
=> (LAMBDA (X) X)
g)
(FUNCALL #'PEPE 'LAMBDA '((X) X))
Inteligencia Artificial e I.C.. 2004/05
3.7
Dpto. Leng. Ciencias Comp.
=> Error: PEPE no tiene significado funcional.
h)
(PEPE 'LAMBDA '((X) X))
=> Error: PEPE no tiene significado funcional.
i)
(JUAN 'LAMBDA '((X) X))
=> Error: JUAN no tiene significado funcional.
j)
(FUNCALL #'(LAMBDA (X) (* X X)) 7)
=> 49
k)
(FUNCALL #'AND T NIL T)
=> Error: el objeto-procedimiento no es una función.
El primer argumento de FUNCALL, es decir, el argumento funcional, debe ser un objetoprocedimiento; en otro caso se produce un error. Sin embargo, hay una excepción a esta norma: si
el argumento funcional es un nombre de función, FUNCALL recupera automáticamente su
significado funcional. Este pequeño remiendo en la semántica de Common Lisp se denomina
coerción implícita y se debe a razones históricas.
Según esto
l)
(FUNCALL '+ 2 3)
=> 5
m)
(FUNCALL (QUOTE DEF-US) 'LAMBDA)
=> (LAMBDA LAMBDA LAMBDA)
n)
(FUNCALL JUAN 'LAMBDA '((X) X))
=> (LAMBDA (X) X)
Inteligencia Artificial e I.C.. 2004/05
3.8
Dpto. Leng. Ciencias Comp.
R.3.4. Objetos-procedimiento como argumento: APPLY.
Suponiendo evaluada (DEFUN DEF-US (X) (LIST X X X)), el símbolo PEPE ligado al
resultado de (FUNCTION CONS) y el símbolo LISTA ligado a la lista (2 3 4), evaluar las
siguientes expresiones:
a)
(APPLY EXPT '(2 3))
b)
(APPLY DEF-US '(A))
c)
(APPLY #'MAX LISTA)
d)
(APPLY (FUNCTION DEF-US) 'A)
e)
(APPLY PEPE '(A (B)))
f)
(APPLY #'(LAMBDA (X) (* X X)) (7))
g)
(APPLY #'AND '(T NIL T))
h)
(APPLY '+ LISTA)
i)
(APPLY (QUOTE DEF-US) '(LAMBDA))
**************************
SOLUCION:
La función predefinida APPLY permite aplicar un objeto-procedimiento a la lista de sus
argumentos.
(APPLY arg-funcional lista-args)
-APPLY es una función propiamente dicha, es decir, evalúa todos sus argumentos.
-tiene exactamente dos argumentos.
-el primer argumento debe ser un objeto-procedimiento F.
-el segundo argumento de APPLY debe ser una lista formada por elementos arg1, ..., argn
compatibles en número y tipo con los requeridos por F.
-el valor devuelto es F(arg1, ..., argn).
Según esto
a)
(APPLY EXPT '(2 3))
=>Error: EXPT sin ligar.
b)
(APPLY DEF-US '(A))
=>Error: DEF-US sin ligar.
c)
(APPLY #'MAX LISTA)
=> 4
d)
(APPLY (FUNCTION DEF-US) 'A)
=> Error: A no es una lista.
e)
(APPLY PEPE '(A (B)))
=> (A B)
f)
(APPLY #'(LAMBDA (X) (* X X)) '(7))
=> 49
g)
(APPLY #'AND '(T NIL T))
=> Error: el objeto-procedimiento no es una función.
Las mismas observaciones sobre la coerción son válidas para APPLY. Según esto
h)
(APPLY '+ LISTA)
=> 9
i)
(APPLY (QUOTE DEF-US) '(LAMBDA))
=> (LAMBDA LAMBDA LAMBDA)
NOTA: En realidad, el número de argumentos de APPLY es indefinido. La auténtica definición de APPLY es
esta: APPLY LISTa todos sus argumentos, salvo el primero y el último, y a continuación APPENDa éste; la
lista resultante contiene los argumentos que se pasan al argumento funcional. Por ejemplo,
(APPLY #'+ 1 2 '(3 4)) == (APPLY #'+ '(1 2 3 4)) => 10
Inteligencia Artificial e I.C.. 2004/05
3.9
Dpto. Leng. Ciencias Comp.
R.3.5. Objetos-procedimiento como argumento: funciones definidas.
Escribir definiciones Lisp de las siguientes funciones:
a) la función sumatorio, que tiene como argumentos una función f : R—>R y dos números
naturales i0, in; sumatorio devuelve f(i0) + f (i0+1) +... + f (in) si i0 ≤ in, 0 en otro caso; y la función
productorio, que tiene como argumentos una función f : R—>R y dos números naturales i0, in;
productorio devuelve f(i0) × f (i0+1) ×... × f(in) si i0 ≤ in, 1 en otro caso.
b)la función acumular, que tiene como argumento:
-una función f : R—>R
-dos números naturales i0, in
-un número valor-inicial
-una operación conmutativa y asociativa acum : R2—>R;
acumular devuelve f(i0) acum f(i0+1)... acum f(in) si i0 ≤ in, valor-inicial en otro caso.
c) la función búsqueda-dicotómica, que tiene como argumentos una función numérica f:R—> R y
dos números a, b tales que f tiene una raíz en [a, b]; búsqueda-dicotómica devuelve precisamente
el valor de esa raíz.
**************************
SOLUCION:
a) Demos una definición recursiva de sumatorio: si i0 > in, se devuelve 0; en otro caso, se
devuelve la suma de f(i0) y el valor del sumatorio desde i0+1 hasta in. En Lisp
(DEFUN SUMATORIO (F I0 IN)
(COND ((> I0 IN) 0)
( T (+ (FUNCALL F I0)
(SUMATORIO F (1+ I0) IN)))))
Y una definición recursiva de productorio: si i0>in, se devuelve 1; en otro caso, se devuelve el
producto de f(i0) y el valor del productorio desde i0+1 hasta in. En Lisp
(DEFUN PRODUCTORIO (F I0 IN)
(COND ((> I0 IN) 1)
( T (* (FUNCALL F I0)
(PRODUCTORIO F (1+ I0) IN)))))
b) Las dos funciones del apartado anterior son muy parecidas; podemos abstraer la operación y
considerarla como otro argumento (lo mismo con el valor inicial). Quedará
(DEFUN ACUMULAR (F I0 IN V-INI ACUM)
(COND ((> I0 IN) V-INI)
( T (FUNCALL ACUM (FUNCALL F I0)
(ACUMULAR F (1+ I0) IN V-INI ACUM)))))
c) El ejercicio ya está prácticamente resuelto en R.2.4: ahora basta abstraer la función y el intervalo
y considerarlos argumentos. El procedimiento principal será ahora
(DEFUN BUSQUEDA-DICOTOMICA (F A B)
(PTO-MEDIO (BUSCAR0 (HACER-ESTADO F A B))))
El constructor HACER-ESTADO es ahora
(DEFUN HACER-ESTADO (F X Y)
(LIST X Y (FUNCALL F X) (FUNCALL F Y) F))
Añadimos el selector
(DEFUN FUNCION-ESTADO (E) (NTH 4 E))
Y modificamos ELEGIR-SUC
(DEFUN ELEGIR-SUC (E)
(COND ((MISMO-SIGNO (FUNCALL (FUNCION E) (PTO-MEDIO E)) (FIZQ E))
(HACER-ESTADO (FUNCION-ESTADO E) (PTO-MEDIO E) (DER E)))
(T (HACER-ESTADO (FUNCION-ESTADO E) (IZQ E) (PTO-MEDIO E)))))
Inteligencia Artificial e I.C.. 2004/05
3.10
Dpto. Leng. Ciencias Comp.
R.3.6. Funciones MAP.
Definir las siguientes funciones:
a) la función mapa-b, que tiene tres argumentos: una función f (de un argumento) y dos números
enteros n, m. mapa-b devuelve una lista formada por los resultados de aplicar f a n, n+1, n+2, ... m
(NIL si n > m).
b)la función mi-mapcar, que tiene dos argumentos: una función f (de un argumento) y una lista L.
mi-mapcar devuelve la lista formada aplicando f a cada elemento de L. Por ejemplo, si f es CAR y L
es ((A B) (C D)) mi-mapcar debe devolver (A C).
c)la función mi-maplist, análoga a mi-mapcar, con la diferencia de que aplica f sucesivamente a L,
a CDR(L), a CDDR(L), .... mientras no se llegue a NIL. Por ejemplo, si f está definido por (LAMBDA
(X) (CONS 'DIGO X)) y L es (QUE SI) el resultado debe ser ((DIGO QUE SI) (DIGO
SI))
d)la función mi-mappendcar, análoga a mi-mapcar, con la diferencia de que agrupa los diversos
resultados con APPEND en lugar de LIST.
e)la función mi-mappendlist, análoga a mi-maplist, con la diferencia de que agrupa los diversos
resultados con APPEND en lugar de LIST.
**************************
SOLUCION:
a)Recursión en N: si n > m, se devuelve NIL. En otro caso, mapa-b CONSa f(n) con el resultado de
aplicar mapa-b a f, n+1 y m. En Lisp
(DEFUN MAPA-B (F N M)
(COND ((> N M) NIL)
( T (CONS (FUNCALL F N) (MAPA-B F (1+ A) B)))))
b)Recursión sobre la lista L: Si L es NIL, entonces mi-mapcar devuelve NIL. En otro caso, mimapcar de L se obtiene CONSando el resultado de aplicar f a CAR(L) y el resultado de aplicar mimapcar a f y CDR(L). En Lisp:
(DEFUN MI-MAPCAR (F L)
(COND ((NULL L) NIL)
( T (CONS (FUNCALL F (CAR L)) (MI-MAPCAR F (CDR L))))))
NOTA: existe la función predefinida MAPCAR, algo más general que MI-MAPCAR. MAPCAR tiene
como primer argumento una función f de cualquier número de argumentos. Los restantes
argumentos de MAPCAR son listas. MAPCAR va aplicando f a tuplas formadas por un elemento de
cada lista, hasta que se agota alguna de ellas. Por ejemplo,
(MAPCAR #'(LAMBDA (X Y) (+ X Y)) '(1 2 3) '(200 100))
=> (201 102)
c) Recursión sobre la lista L: si L es NIL, entonces, mi-maplist devuelve NIL. En otro caso, mimaplist de L se obtiene CONSando el resultado de aplicar f a L y el resultado de aplicar mi-maplist
a f y CDR(L). En Lisp:
(DEFUN MI-MAPLIST (F L)
(COND ((NULL L) NIL)
( T (CONS (FUNCALL F L) (MI-MAPLIST F (CDR L))))))
NOTA: existe la función predefinida MAPLIST, algo más general que MI-MAPLIST. MAPLIST tiene
como primer argumento una función f de cualquier número de argumentos. Los restantes
argumentos de MAPLIST son listas. MAPLIST va aplicando f a tuplas formadas por las listas, los
CDR de las listas, los CDDR de las listas, ... hasta que se agota alguna de ellas. Por ejemplo,
(MAPLIST #'(LAMBDA (X Y) (APPEND X Y X)) '(A B) '(X Y Z))
=> ((A B X Y Z A B) (B Y Z B))
Inteligencia Artificial e I.C.. 2004/05
3.11
Dpto. Leng. Ciencias Comp.
NOTA: Un empleo impremeditado de MAPLIST puede llevar a computaciones redundantes.
d)Basta aplicar APPEND al resultado de MAPCAR:
(DEFUN MI-MAPPENDCAR (F L)
(APPLY #'APPEND (MAPCAR F L)))
NOTA: existe la función predefinida MAPCAN -versión destructiva de MI-MAPPENDCAR- que emplea
NCONC en lugar de APPEND (vd. lección 8).
e)Basta aplicar APPEND al resultado de MAPLIST:
(DEFUN MI-MAPPENDLIST (F L)
(APPLY #'APPEND (MAPLIST F L)))
NOTA: existe la función predefinida MAPCON -versión destructiva de MI-MAPPENDLIST- que
emplea NCONC en lugar de APPEND (vd. lección 8).
Inteligencia Artificial e I.C.. 2004/05
3.12
Dpto. Leng. Ciencias Comp.
R.3.7. Uso de funciones MAP.
Empleando funciones MAP, escribir definiciones Lisp de las funciones siguientes:
a) la suma de vectores. Los vectores se representarán mediante listas de números.
b) el apareamiento de L1 y L2, que es la lista formada por listas de dos elementos,
tomados el primero de L1 y el segundo de L2. Por ejemplo, el apareamiento de (DO RE MI) y (C D
E) es ((DO C) (RE D) (MI E)). Si las listas son de distinta longitud, se aparean hasta que una de
ellas se acabe. Por ejemplo, (A) y (X Y Z) dan ((A X)).
c) poner-comillas, que tiene como argumento una lista (e1 e2 ...) y devuelve la lista ('e1 'e2
...).
d) la distancia entre dos puntos. Los puntos se representarán por listas de números.
e) la lista desnuda o linealizada obtenida a partir de una lista con anidamientos (vd. R.2.6)
**************************
SOLUCION:
a)Para resolver problemas con funciones MAP, descomponemos el problema inicial de la siguiente
forma:
-procesar cada elemento de la lista de la forma adecuada. Esto queda reflejado en el
argumento funcional de la función MAP.
-componer los resultados de estos procesamientos de forma adecuada. Esto queda
reflejado en la elección de la función MAP (MAPCAR, MAPCAN, MAPPENDCAR, ...). A veces también
es necesario aplicar otros pasos posteriores de procesamiento.
En el caso de la suma vectorial:
-hay que sumar cada elemento de V1 con el correspondiente de V2. El argumento
funcional será #'+.
-hay que formar una lista con los resultados. La función será MAPCAR.
En Lisp
(DEFUN SUMA-VECTORIAL (V1 V2)
(MAPCAR #'+ V1 V2))
NOTA: "Las funciones MAP deberían usarse siempre que su aplicación sea natural, puesto que
esto aumenta la claridad del código" [CLtL2], p. 172.
b)Tenemos que hacer lo siguiente: para cada elemento de L1, formar una lista con él y el
correspondiente de L2; y formar una lista con los resultados. En Lisp
(DEFUN APAREAR (L1 L2)
(MAPCAR #'LIST L1 L2))
c)Tenemos que hacer lo siguiente:
-para cada elemento e de L, formar la lista (QUOTE e). No hay ninguna función predefinida
que haga exactamente esto; pero no es necesario (ni conveniente) emplear DEFUN para definir
este proceso. En lugar de ello, escribimos directamente la definición en la llamada a MAPCAR.
-formar una lista con los resultados.
En Lisp
(DEFUN PONER-COMILLAS (L)
(MAPCAR #'(LAMBDA (X) (LIST 'QUOTE X)) L))
d)Tenemos que hacer lo siguiente:
-para cada par de elementos correspondientes e, e', calcular (e - e')2.
-formar una lista con los resultados.
-sumar todos los elementos de la lista y hallar la raíz cuadrada de la suma.
En Lisp
Inteligencia Artificial e I.C.. 2004/05
3.13
Dpto. Leng. Ciencias Comp.
(DEFUN DISTANCIA (P1 P2)
(SQRT
(APPLY #'+
(MAPCAR #'(LAMBDA (X Y) (SRQT (- X Y))) P1 P2))))
e)Tenemos que hacer lo siguiente:
-para cada elemento e, calcular su linealización. Nótese que ello implica una definición
recursiva. El caso base se dará cuando e sea un átomo.
-APPENDar los resultados. Por tanto, en el caso base se debe devolver la lista (e).
En Lisp
(DEFUN DESNUDAR (L)
(COND ((ATOM L) (LIST L))
( T (MI-MAPPENDCAR #'DESNUDAR L))))
NOTA: MI-MAPPENDCAR no es una función predefinida. Se define en R.3.6.
Inteligencia Artificial e I.C.. 2004/05
3.14
Dpto. Leng. Ciencias Comp.
R.3.8. Cierres léxicos.
Evaluar las siguientes formas Lisp en el orden dado:
a)
(DEFUN F1 (X)
(APPEND X L2))
b)
(DEFUN F2 (L1 L2)
(F1 L1))
c)
(F2 '(Y PUNTO) '(HE DICHO))
d)
(DEFUN G0 ()
#'(LAMBDA (X) (APPEND X '(Y PUNTO))))
e)
(G0)
f)
(FUNCALL (G0) '(COMA))
g)
(DEFUN G1 (L)
#'(LAMBDA (X) (APPEND X L)))
h)
(G1 '(COMA))
i)
(FUNCALL (G1 '(Y PUNTO)) '(COMA))
**************************
SOLUCION:
a)
(DEFUN F1 (X)
(APPEND X L2))
=> F1
b)
(DEFUN F2 (L1 L2)
(F1 L1))
=> F2
c)Recuérdese lo explicado en R.1.8 sobre la creación de entornos: Se crea un entorno E1 para
evaluar la expresión completa
(F2 '(Y PUNTO) '(HE DICHO)) ==
L1<- (Y PUNTO)
L2<- (HE DICHO)
(F1 L1)
y para evaluar esta subexpresión se crea otro entorno E2:
(F1 L1) ==
X<- (Y PUNTO)
(APPEND X L2))
X es parámetro de F1 y por tanto se liga al valor del argumento (Y PUNTO). Sin embargo, en el
entorno E2 L2 está sin ligar y por tanto no se puede evaluar. El resultado final es pues
=> Error: L2 sin ligar.
Sin embargo L2 estaba ligado en el entorno E1, desde donde se creó el entorno E2. Ello no
importa: las ligaduras de E1 son irrelevantes en los entornos creados a partir de él. Esto se suele
expresar diciendo que Common Lisp crea entornos léxicos.
d)
(DEFUN G0 ()
#'(LAMBDA (X) (APPEND X '(Y PUNTO))))
=> G0
e)
(G0)
=> #<función 1 #xDFF024>
(una función de X que APPENDa X y la lista (Y PUNTO))
f)
(FUNCALL (G0) '(COMA))
El primer argumento es
(G0) => una función de X que APPENDa X y la lista (Y PUNTO)
El segundo argumento es (COMA)
FUNCALL aplica el primer argumento al segundo y produce
(COMA Y PUNTO)
Inteligencia Artificial e I.C.. 2004/05
3.15
Dpto. Leng. Ciencias Comp.
g)
(DEFUN G1 (L)
#'(LAMBDA (X) (APPEND X L)))
=> G1
h)
(G1 '(COMA))
=> #<cierre 1 #xE0F824>
(una función de X que APPENDa X y la lista L)
Nótese que Lisp no afirma devolver una función, sino un cierre. ¿Cuál es la diferencia? El siguiente
ejemplo lo aclarará:
i)
(FUNCALL (G1 '(Y PUNTO)) '(COMA)) ==
FUNCALL evalúa sus argumentos. El primero es una llamada a G1, luego se crea un entorno para
evaluarla:
(G1 '(Y PUNTO)) ==
L<- (Y PUNTO)
#'(LAMBDA (X) (APPEND X L)))
=> #< cierre 1 #xE0F811>
FUNCALL aplica esta función devuelta por G1 al segundo argumento (COMA):
((LAMBDA (X) (APPEND X L)) '(Y PUNTO))
y el resultado dependerá del valor al que esté ligado L. Pero L era el parámetro de G1, y ya no
estamos en el entorno de evaluación de G1; por lo tanto, podría esperarse que el resultado fuera
=> Error: L1 sin ligar.
Sin embargo, no es así. Para justificar esto, tenemos que introducir el concepto de cierre léxico y
modificar la descripción dada en R.3. 2 de la forma especial FUNCTION.
Un cierre léxico es un par formado por un objeto-procedimiento F y un entorno. Cuando se aplique
F, siempre habrá de hacerse en este entorno.
Ahora podemos dar la descripción completa de FUNCTION, que es como sigue:
(FUNCTION argumento)
-un solo argumento, que debe ser un símbolo o una expresión lambda.
-FUNCTION toma literalmente su argumento.
-el valor devuelto es:
-si el argumento es un símbolo, el objeto-procedimiento que es el significado funcional del
símbolo.
-si el argumento es una expresión lambda, un cierre léxico. Un cierre léxico es un objetoprocedimiento que además conserva una referencia al entorno vigente durante la evaluación de
FUNCTION.
Hasta ahora todas las llamadas a FUNCTION se habían realizado en un entorno vacío, por lo que
no había sido necesario introducir el concepto de cierre léxico. Pero al evaluar
(G1 '(Y PUNTO))
se produce una llamada a FUNCTION:
#'(LAMBDA (X) (APPEND X L)))
en el entorno
L<- (Y PUNTO)
Por tanto el resultado es un cierre léxico:
=> #<cierre léxico 10A>#
que representaremos gráficamente como
L<- (Y PUNTO)
(LAMBDA (X) (APPEND X L)))
Y tras esta explicación podemos justificar que
(FUNCALL (G1'(Y PUNTO)) '(HE DICHO)) ==
L<- (Y PUNTO)
(LAMBDA (X) (APPEND X L))
'(HE DICHO)
=> (Y PUNTO HE DICHO)
Los cierres léxicos permiten crear en tiempo de ejecución funciones "variables", es decir, funciones
cuya definición depende del entorno en que se crean. Por ejemplo, una llamada a la función
anterior (G1 argG1) crea una función F(argf) que modifica argf de una forma que depende del
valor que tuviera argG1.
Inteligencia Artificial e I.C.. 2004/05
3.16
Dpto. Leng. Ciencias Comp.
R.3.9. Funciones que devuelven cierres léxicos.
Escribir definiciones Lisp de las funciones siguientes:
a)la función composición de dos funciones de un argumento.
b)la función que devuelve la función suma de dos funciones de un argumento numérico.
c)la función que aproxima la función derivada de una función real de una variable real
(supóngase una función sin argumentos deltax que da el incremento de x para calcular la
aproximación).
d)la función que tiene como argumentos una función f de un argumento y un natural n, y
devuelve la función iterada f n.
**************************
SOLUCION:
a)Nótese que COMPOSICION devuelve un objeto-procedimiento más unas ligaduras, es decir, un
cierre léxico. La única manera de conseguir esto es emplear FUNCTION. Por otra parte, la
composición de f y g es la función que aplicada a x devuelve f(g (x)). En Lisp
(DEFUN COMPOSICION (F G)
#'(LAMBDA (X) (FUNCALL F (FUNCALL G X))))
b) la definición de SUMA-FUNCIONAL es sencilla: la función de f y g que devuelve la función que
aplicada a x devuelve f(x) + g(x). En Lisp
(DEFUN SUMA-FUNCIONAL (F G)
#'(LAMBDA (X) (+ (FUNCALL F X) (FUNCALL G X))))
c) Recordemos que la derivada de f en x se define como el límite de
f(x + dx) - f(x)
−−−−−−−−−−
dx
cuando dx tiende a 0. Podemos aproximarla por el valor de este cociente cuando dx es pequeño.
En Lisp
(DEFCONSTANT DELTAX 1D-6)
(DEFUN DERIVADA (F)
#'(LAMBDA (X)
(/ (- (FUNCALL F (+ DELTAX X))
(FUNCALL F X))
DELTAX)))
d) Recursión sobre n: si n=0, la función devuelta es la identidad; en otro caso, el resultado de
componer f con el valor devuelto para n -1. Empleando la función composición será
(DEFUN ITERACION (F N)
(COND ((ZEROP N) #'(LAMBDA (X) X))
(T (COMPOSICION F (ITERACION F (1- N))))))
o bien directamente
(DEFUN ITERACION (F N)
(COND ((ZEROP N) #'(LAMBDA (X) X))
(T #'(LAMBDA (X)
(FUNCALL F (FUNCALL (ITERACION F (1- N)) X))))))
Inteligencia Artificial e I.C.. 2004/05
3.17
Dpto. Leng. Ciencias Comp.
R.3.10. Uso de funciones MAP (II).
Empleando funciones MAP, escribir definiciones Lisp de las funciones siguientes:
a)sustituir-todo, que dados una lista de símbolos L y dos símbolos sv, sn, devuelve la lista
originada a partir de L sustituyendo todas las apariciones de sv (como elemento de L) por sn.
b)sustituir-prof, que dados una lista de símbolos L y dos símbolos sv, sn, devuelve la lista
originada a partir de L sustituyendo todas las apariciones de sv (como elemento de L o elemento
de alguno de los elementos de L, etc. ...) por sn.
c)producto-cartesiano, que dadas dos listas de símbolos sin repeticiones L1 y L2 devuelve
la lista de todos los pares formados por un elemento de L1 y otro de L2.
c)permutaciones, que dada una lista de símbolos sin repeticiones L devuelve la lista de
todas las permutaciones de L (consideradas como listas).
**************************
SOLUCION:
a)Tenemos que hacer lo siguiente:
-para cada elemento e, sustituirlo por sn (si es sv) o dejarlo inalterado (si es distinto de sv).
-LISTar los resultados.
El lector poco atento puede sugerir la siguiente implementación:
(DEFUN SUST-AUX (X)
(IF (EQ X SV) SN X))
(DEFUN SUSTITUIR-TODO (SN SV L)
(MAPCAR #'SUST-AUX L))
Pero esta implementación es completamente incorrecta. En efecto, la llamada a SUST-AUX desde
MAPCAR siempre produce un error, ya que SV y SN están sin ligar en el entorno creado al llamar a
SUST-AUX.
La solución es emplear #´ para generar un cierre léxico:
(DEFUN SUSTITUIR-TODO (SN SV L)
(MAPCAR (SUST-AUX SN SV) L))
(DEFUN SUST-AUX (SN SV)
#'(LAMBDA (X) (IF (EQ X SV) SN X)))
Pero, ¿pará que definir una función auxiliar? La mejor solución es simplemente
(DEFUN SUSTITUIR-TODO (SN SV L)
(MAPCAR #'(LAMBDA (X) (IF (EQ X SV) SN X)) L))
b)Tenemos que hacer lo siguiente:
-para cada elemento e, si es un átomo, sustituirlo por sn (si es sv) o dejarlo inalterado (si
es distinto de sv). Si e es una lista, sustituirla por el resultado de aplicarle sustituir-prof.
-LISTar los resultados.
(DEFUN SUSTITUIR-PROF (SN SV L)
(MAPCAR
#'(LAMBDA (X)
(COND ((ATOM X) (IF (EQ X SV) SN X))
(T (SUSTITUIR-PROF SN SV X))))
L))
c)Tenemos que hacer lo siguiente:
-para cada elemento s1 de L1, formar una lista con todos los pares de la forma (s1, s2),
siendo s2 de L2.
-APPENDar los resultados.
A su vez, para la primera parte tendremos que
-para cada elemento s2 de L2, formar la lista (s1, s2).
-LISTar los resultados.
Esto último se consigue con
Inteligencia Artificial e I.C.. 2004/05
3.18
Dpto. Leng. Ciencias Comp.
(MAPCAR #'(LAMBDA (S2) (LIST S1 S2)) L2))
Nótese que S1 está libre en esta expresión, pero si S1 está ligado en una expresión exterior la
presencia de #' asegura que este valor se conserva al aplicar (LAMBDA (S2) (LIST S1 S2))
Por tanto en Lisp la función pedida será
(DEFUN PRODUCTO-C (L1 L2)
(MI-MAPPENDCAR
#'(LAMBDA (S1)
(MAPCAR
#'(LAMBDA (S2) (LIST S1 S2))
L2))
L1))
NOTA: MI-MAPPENDCAR no es una función predefinida. Se define en R.3.6.
d)Tenemos que hacer lo siguiente:
-si L es vacía, la lista de sus permutaciones es (NIL)
-en otro caso
-para cada elemento s de L, hay que considerar todas las permutaciones de L-{s}
y prefijarles s.
-hay que APPENDar los resultados.
Para prefijar s a todas las listas elementos de una lista de listas L-LISTAS podemos definir
(DEFUN PREFIJAR (S L-LISTAS)
(MAPCAR
#'(LAMBDA (L) (CONS S L))
L-LISTAS))
Y finalmente la función pedida es
(DEFUN PERMUTACIONES (L)
(COND ((NULL L) (LIST NIL))
(T (MI-MAPPENDCAR
#'(LAMBDA (S)
(PREFIJAR S (PERMUTACIONES (REMOVE S L))))
L))))
NOTA: MI-MAPPENDCAR no es una función predefinida. Se define en R.3.6.
Inteligencia Artificial e I.C.. 2004/05
3.19
Dpto. Leng. Ciencias Comp.
EJERCICIOS PROPUESTOS.
P.3.1. Suponiendo que no hay símbolos ligados ni más funciones que las predefinidas, evaluar las
siguientes expresiones:
a)
((LAMBDA (LAMBDA) LAMBDA) 'LAMBDA)
b)
((LAMBDA (X) (X)) 'A)
c)
(FUNCTION (QUOTE QUOTE))
d)
(FUNCTION (LAMBDA (A) (+ 3 A)))
e)
(FUNCALL (IF (APPLY #'CDR ((A B))) #'+ #'-) 5 3)
f)
(APPLY #'(LAMBDA (A B) (LIST B A)) (CONS 'A '(B)))
g)
(APPLY #'AND '(2 A 2))
h)
(FUNCALL (AND (FUNCTION CDR) (FUNCTION CAR)) '(TODO FLUYE))
i)
(LAMBDA (A) (FUNCALL (FUNCTION +) A))
j)
((LAMBDA () NIL))
k)
((LAMBDA (X) (FUNCALL X X)) #'(LAMBDA (X) (FUNCALL X X)))
P.3.2. (Stark 90, pg. 91) Dar ejemplos de expresiones Lisp que se puedan evaluar sin error y
tengan la siguiente estructura (x, y, z son expresiones):
a)
(x x)
b)
((x y z))
c)
(x (y y) (z z))
P.3.3. Supongamos que se pasa como argumento F una función de átomos en átomos.
Determinar a qué se evalúa (XX F) si XX se define de la manera siguiente:
a)
(DEFUN XX (F)
#'(LAMBDA (Y) (FUNCALL F Y)) )
b)
(DEFUN XX (F)
#'(LAMBDA (Y) #'(LAMBDA (X) (FUNCALL F X))))
c)
(DEFUN XX (F)
(FUNCALL #'(LAMBDA (Y) #'(LAMBDA (X) (FUNCALL F X))) 'Y))
P.3.4. Supóngase que las funciones se escriben siempre en notación prefija y son asociativas por la
derecha, es decir, fgh es la aplicación de f a la aplicación de g a h. Escribir en CommonLisp las
siguientes definiciones lambda, y explicar qué hacen los objetos-procedimiento así definidos:
a)
λx.x
b)
λx.+xx
c)
λx.λy.x
d)
λx.λy.y
e)
λx.λy.λz.(xz)(yz)
P.3.5.
a)Escribir una lista L que se evalúe a sí misma, es decir, L => L.
b)Escribir una lista L cuyas sucesivas evaluaciones constituyan una sucesión infinita sin
repeticiones, es decir,
L => L1 => L2 ... => Ln => ..., y Li ≠ Lj si i ≠ j
P.3.6. Escribir definiciones Lisp de las siguientes funciones:
a)la función delta, que tiene como argumento una función numérica f y devuelve el número f(0).
b)la función búsqueda-áurea, que tiene como argumentos una función numérica f: R—>R y dos
números a, b tales que f tiene exactamente un extremo, que es un mínimo, en el intervalo (a, b);
búsqueda-áurea devuelve precisamente el valor de ese mínimo.
c)la función integral, que tiene como argumentos una función numérica f:R—>R y dos números a,
b; integral devuelve ∫ab f(x)dx. Supóngase que existe una constante deltax que establece el
espaciamiento de los puntos del eje de las x en los que se calcula f(x).
Inteligencia Artificial e I.C.. 2004/05
3.20
Dpto. Leng. Ciencias Comp.
P.3.7. Definir las siguientes funciones:
a)map-delta, que tiene como argumentos una función f y tres números v0, vf, delta, y devuelve la
lista formada aplicando f a v0, v0+delta, ..., hasta que se alcanza o supera vf.
b)map-sucs, que tiene como argumentos una función f, dos números v0 y vf y una función suc, y
devuelve la lista formada aplicando f a v0, suc(v0), suc(suc(v0))..., hasta que se alcanza vf.
Expresar map-delta mediante map-sucs.
c)maprecur, que tiene como argumentos una función f y una lista con anidamientos L, y devuelve la
lista formada sustituyendo en L cada átomo x por f(x). Por ejemplo, si f es la función sucesor y L es
((2 (3 4) 0) 1), maprecur devuelve ((3 (4 5) 1) 2)
P.3.8. Definir las siguientes funciones:
a) MI-FIND-IF, que tiene como argumentos un predicado p y una lista L, y devuelve el primer
elemento de L que satisface p o falso si ninguno lo satisface.
b) MI-EVERY, que tiene como argumentos un predicado p y una lista L, y devuelve falso si algún
elemento de L no satisface p o verdadero en otro caso.
c) MI-COUNT-IF, que tiene como argumentos un predicado p y una lista L, y devuelve el número
de elementos de L que satisfacen p.
d) Criticar la siguiente implementación de MI-FIND-IF:
(DEFUN MI-FIND-IF (P L) (APPLY #'OR L))
P.3.9. Usando funciones MAP, definir las siguientes funciones:
a)hinchar-estadísticas, que dada una lista numérica L y un porcentaje n, devuelve la lista formada
incrementando en un n% todos los elementos de L.
b)el módulo de un vector, representado por una lista de números.
c)el producto escalar de dos vectores.
d)la desviación típica de un conjunto de números, representados en una lista.
e) la lista intersección de dos listas de símbolos sin repeticiones.
f) la lista unión de dos listas de símbolos sin repeticiones.
P.3.10. Definir las siguientes funciones:
a)la función que a partir de un conjunto C devuelve su función característica χ(x), que vale 0 si
x∉ C, 1 si x∈ C.
b)la función proyección de una función de dos argumentos, definida como sigue: la función
proyección tiene dos argumentos, una función f y un entero n = 1, 2, que indica si se trata de la
primera o la segunda proyección. La n-ésima proyección de f se obtendrá haciendo NIL todos los
argumentos de f salvo el n-ésimo.
c)la función suavizar, que tiene como argumentos una función f : R—>R, un número natural n, un
número real δ y una función suavización : R2n+1—>R. suavizar devuelve la función f suavizada
según suavización, es decir, la función que a x le hace corresponder
suavización(f(x - nδ), f(x - (n-1)δ), ... f(x + δ), f(x), f(x + δ), ...., f(x + nδ))
Inteligencia Artificial e I.C.. 2004/05
3.21
Dpto. Leng. Ciencias Comp.
NOTAS ERUDITAS Y CURIOSAS.
El uso de la notación lambda ha hecho creer a muchos que las relaciones entre
lambda-cálculo (Church 41, Barendregt 84, Revesz 88) y Lisp son más estrechas de lo que
realmente son. Sin embargo, considérense estas
modestas afirmaciones de McCarthy
(McCarthy,
1981): “La manera de hacer esto [manejar las
funciones como datos] fue tomar prestada del lambdacálculo de Church la notación lambda ... Uno de los
mitos acerca de Lisp es que se trata de una
implementación del lambda-cálculo, o que esa era
nuestra intención. La verdad es que yo no comprendía
realmente el lambda-cálculo. En particular, no
comprendía que se pueden hacer expresiones
condicionales en el lambda-cálculo puro. Así que no se
trataba de hacer una versión práctica del lambdacálculo, aunque si alguien hubiera comenzado con esa
intención podría haber acabado con algo parecido a
Lisp”.
La versión original de Lisp (LISP 1.5) no
proporcionaba ningún recurso de programación que
permitiera definir “funciones variables”. Esta carencia,
rápidamente detectada, fue denominada en la jerga
Fig. III. 1. Alonzo Church.
de los programadores Lisp el “problema FUNARG” y
su solución fue la definición del ámbito léxico para las
ligaduras (vd. lección 5) y su “congelación” mediante FUNCTION. En (Moses 70) se expone la
historia de este problema.
El dialecto Scheme emplea sistemáticamente las reglas léxicas, por lo cual el uso de la
forma FUNCTION es innecesario. Sin embargo, en CommonLisp se ha optado por la solución
más tradicional.
Lisp permite emplear los objetos-procedimiento como argumentos y valores de las
funciones. Por ello puede decirse que es un lenguaje de programación -aunque no
exclusivamente- funcional. En esta lección se ha presentado una primera técnica típicamente
funcional: el uso de funciones MAP. En la lección siguiente seguimos desarrollando este tema.
Inteligencia Artificial e I.C.. 2004/05
3.22
Dpto. Leng. Ciencias Comp.
Descargar