El paradigma funcional (4)
Table of Contents
- Bibliografía de hoy
- Índice del tema
- Características de la programación funcional (repaso)
- Ejemplo de dualidad datos y programas calculadora
- Ejemplo avanzado
- Datos compuestos en Scheme
- Cómo dibujamos las parejas
- Funciones de acceso a una pareja
- Definición declarativa
- Nota histórica
- Podemos hacer parejas con cualquier tipo de datos
- Un ejemplo más complicado
- Seguimos en el paradigma funcional
- Las parejas son un tipo de dato de primer orden
- Propiedad de clausura: parejas de parejas
- Ejemplos y figuras de parejas
- Funciones c????r
- Función
pair? - Repaso de listas
- Construcción de listas con parejas
Carycdrpara recorrer listasconspara formar una nueva lista
Bibliografía de hoy
- Capítulo 2.2 Abelson & Sussman
- Capítulo 10 PLP: Functional Languages
Índice del tema
- Historia del paradigma funcional
- Características del paradigma funcional puro
- Modelo de computación basado en sustitución
- Características de la programación funcional (LISP, Scheme)
Características de la programación funcional (repaso)
- Evaluación sin efectos laterales: paradigma declarativo y modelo de sustitución
- Funciones como tipos de datos de primer orden: forma especial
lambda - Ámbitos de variables: forma especial
let - Dualidad entre datos y programas: formas especiales
evalyapply - Listas como elemento fundamental de procesamiento: parejas,
cons,car,cdr - Recursión
Ejemplo de dualidad datos y programas calculadora
(define (calculadora) (display "Introduce parámetros entre paréntesis: ") (define params (read)) (display "Introduce cuerpo") (define cuerpo (read)) (define func (eval (append '(lambda) (list params) (list cuerpo)))) (display "Introduce argumentos entre paréntesis: ") (define args (read)) (apply func args))
Nota: Este programa no es funcional; realiza pasos de ejecución para leer las expresiones introducidas por el usuario y para imprimir el resultado de su evaluación.
Es importante darse cuenta de que la expresión
(append '(lambda) (list params) (list cuerpo))
devuelve una lista que es una expresión lambda correcta, cuya evaluación va a crear un procedimiento al que se llama después.
Por ejemplo, supongamos que:
(define params '(x y)) (define cuerpo '(+ x y))
Si hiciéramos (append '(lambda) params cuerpo) obtendríamos una
lista con 6 elementos:
(append '(lambda) params cuerpo) -> (lambda x y + x y)
No es lo que queremos; necesitamos obtener la lista (lambda (x y) (+ x y)), una lista de 3 elementos cuyo segundo y tercer elemento son a
su vez listas. Eso es lo que hace la expresión:
(append '(lambda) (list params) (list cuerpo)) -> (lambda (x y) (+ x y))
Después la llamada a eval hace el resto.
Ejemplo avanzado
El bucle read-eval-print en Scheme:
(define (rep-loop)
(display "mi-interprete> ") ; imprime un prompt
(let ((expr (read))) ; lee una expresión
(cond
((eq? expr 'adios) ; el usuario quiere parar?
(display "saliendo del bucle read-eval-print")
(newline))
(else ; en otro caso
(write (eval expr)) ; evaluar e imprimir
(newline)
(rep-loop)))))
Datos compuestos en Scheme
- En Scheme es posible crear datos compuestos.
- La forma de hacerlo es definiendo una construcción muy simple y usando esa construcción simple para hacer cosas más complicadas.
- El tipo de dato compuesto más simple es la pareja: una entidad formada por dos elementos.
- Se utiliza la función
conspara construirla.
Ejemplo:
(cons 1 2) -> (1 . 2) (define c (cons 1 2))
Cómo dibujamos las parejas
Funciones de acceso a una pareja
- Podemos obtener el elemento correspondiente a la parte izquierda
con el operador
cary su parte derecha con el operadorcdr
Ejemplos:
(define c (cons 1 2)) (car c) -> 1 (cdr c) -> 2
Definición declarativa
Las funciones cons, car y cdr quedan perfectamente definidas con las
siguientes ecuaciones:
(car (cons x y)) = x (cdr (cons x y)) = y
Nota histórica
- ¿De dónde vienen los nombres car y cdr?
- Realmente los nombres eran CAR y CDR (en mayúsculas)
- La historia se remonta al año 1959, en los orígenes del LISP y tiene que ver con el nombre que se les daba a ciertos registros de la memoria del IBM 709.
Explicación completa: http://www.iwriteiam.nl/HaCAR_CDR.html
Podemos hacer parejas con cualquier tipo de datos
Es posible construir una pareja con cualquier tipo de datos, mezclando distintos tipos de datos:
(define c (cons 'hola #f)) (car c) -> 'hola (cdr c) -> #f
Un ejemplo más complicado
(define p1 (cons (lambda (x) (+ x 3))
5))
¿Cómo se podría llamar a la función de la parte izquierda de la pareja con la parte derecha como argumento?
((car p1) (cdr p1)) -> 8
Podríamos incluso definir una función que trabajara con esta estructura:
(define (procesa-pareja p) ((car p) (cdr p)))
Seguimos en el paradigma funcional
- Seguimos en el paradigma funcional
- Una vez creada una pareja no es posible modificar sus contenidos.
- Scheme tiene primitivas para modificar el contenido de las parejas.
Las parejas son un tipo de dato de primer orden
Una pareja es también un tipo de datos de primer orden: puede pasarse como argumento y devolverse como resultado de una función.
Propiedad de clausura: parejas de parejas
- Las parejas pueden formar parte de otras parejas.
- Esta última propiedad se denomina clausura de la operación
cons. - El resultado de un
conspuede usarse para construir otros conses (parejas).
Ejemplo:
(define p1 (cons 1 2)) (define p2 (cons 3 4)) (define p (cons p1 p2))
Expresión equivalente
(define p (cons (cons 1 2)
(cons 3 4)))
Podríamos representar esta estructura de esta forma:
Pero se haría muy complicado representar muchos niveles de anidamiento. Por eso utilizamos la siguiente representación, entendiendo las flechas como contiene y no como referencia.
Ejemplos y figuras de parejas
(define p (cons (cons 1
(cons 3 4))
2))
¿Qué figura representaría la estructura anterior?
Funciones c????r
(cdr (cdr (car p))) -> 4
Es equivalente a la instrucción cadar de Scheme:
(cddar p) -> 4
- El nombre de la función se obtiene concatenando a la letra "c", las
letras "a" o "d" según hagamos un
caro uncdry terminando con la letra "r" - Hay definidas 24 funciones de este tipo:
caaaar,caaadr, …,cddddr.
Función pair?
La función pair? nos dice si un objeto es atómico o es una pareja:
(pair? 3) -> #f (pair? (cons 3 4)) -> #t
Repaso de listas
(list 1 2 3 4) -> (1 2 3 4) '(1 2 3 4) -> (1 2 3 4) (define hola 1) (define que 2) (define tal 3) (list hola que tal) -> (1 2 3 4) '(hola que tal) -> (hola que tal) (define a '(1 2 3)) (car a) -> 1 (cdr a) -> (2 3) (length a) -> 3 (length '()) -> 0 (append '(1) '(2 3 4) '(5 6 7) '()) -> (1 2 3 4 5 6 7)
Construcción de listas con parejas
Definición recursiva con parejas:
- Una parejas en la que el primer elemento es un dato y el segundo el resto de la lista.
- Un símbolo especial '() que denota la lista vacía
Ejemplo:
(cons (1
(cons 2
(cons 3
'())))))
Car y cdr para recorrer listas
Ahora se entiende mejor por qué las funciones que permiten recorrer
una lista son car y cdr como en el siguiente ejemplo:
(define lista (cons 1 (cons 2 (cons 3 (cons 4 '()))))) (car lista) (cdr lista)
cons para formar una nueva lista
> (define l1 '(1 2 3 4)) > (cons 'hola l1) (hola 1 2 3 4)
Lenguajes y Paradigmas de Programación
Curso 2010-2011
Departamento de Ciencia de la Computación e Inteligencia Artificial
Universidad de Alicante
Sitio web realizado con org-mode y el estilo CSS del proyecto Worg