LPP - Teoria Latex PDF
LPP - Teoria Latex PDF
LPP - Teoria Latex PDF
Universidad de Alicante
JOSE PEREZ MARTINEZ
The Scheme-book
UNIVERSIDAD DE ALICANTE
Ttulo The Scheme-book
Autor: Jose Perez Martnez, jpm33@alu.ua.es
Indice general 3
Indice de guras 5
1. Programacion Funcional 7
1.1. Lenguajes de programacion . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2. Introduccion a Scheme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1. Expresiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2. Evaluacion de una expresion . . . . . . . . . . . . . . . . . . . . . . 9
1.2.3. Denicion de nuevas funciones . . . . . . . . . . . . . . . . . . . . . 10
1.2.4. Quote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
1.2.5. Algunas funciones de Scheme . . . . . . . . . . . . . . . . . . . . . 11
1.2.6. Otros ejemplos de denicion de funciones . . . . . . . . . . . . . . . 11
1.2.7. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.3. Programacion Funcional . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4. Modelo de sustitucion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.4.1. Orden de evaluacion normal vs. de aplicacion . . . . . . . . . . . . 15
2. Recursion 17
2.1. Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2. Procesos recursivos e iterativos . . . . . . . . . . . . . . . . . . . . . . . . 20
2.2.1. Factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.2.2. Numeros de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . . . 23
3
4 INDICE GENERAL
4. Abstraccion de datos 29
5. Datos jerarquicos 31
10.Streams 41
A. Ejemplos de clase 43
A.1. Clase 1. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
A.2. Clase 2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.3. Clase 3. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.4. Clase 4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.5. Clase 5. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.6. Clase 6. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.7. Clase 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.8. Clase 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.9. Clase 9. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.10.Clase 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.11.Clase 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.12.Clase 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.13.Clase 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.14.Clase 14 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.15.Clase 15 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.16.Clase 16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.17.Clase 17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.18.Clase 18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.19.Clase 19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.20.Clase 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.21.Clase 21 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.22.Clase 22 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.23.Clase 23 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.24.Clase 24 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
A.25.Clase 25 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Indice de guras
5
6 INDICE DE FIGURAS
Tema 1
Programacion Funcional
expresiones primitivas, que representan las entidades mas simples que maneja el
lenguaje
mecanismos de abstraccion, con los que los objetos compuestos puede ser nombrados
y manipulados como una unidad.
7
8 1.2. Introduccion a Scheme
1.2.1. Expresiones
Por ejemplo si ejecuatamos en el interprete:
> 2
2
> ( 3 2)
6
> ( sqrt 4)
16
> (+ 2 3 4)
9
Composicion de funciones:
(+ ( 3 4) 5)
( (+ 2 1) (/ 10 2))
Deniciones y entornos
Una caracterstica fundamental de cualquier lenguaje de programacion es la posibilidad
de denir nuevos nombres que van ampliando el vocabulario que podemos usar para
construir programas. Cada nombre nuevo representa un aumento de la capacidad de
expresividad del lenguaje, en la lnea del dominio en el que queremos denir el programa.
Para ser consistentes con el libro de la asignatura, el idioma que vamos a usuar para la
mayora de los nombres que inventemos sera el ingles.
Por ejemplo, si estamos escribiendo un programa de geometra, es normal que de-
namos nombres como square, point, circle, etc . . .
A que le podemos dar nombre? A las entidades propias del lenguaje. En el caso de
Scheme a datos elementales (enteros, strings, . . .) y a funciones.
Si lo de dar nombre a un entero te puede parecer una forma muy retorcida
de explicar un DEFINE de C, ya ni me contaras con lo de dar nombre a una
funcion. Por que esa forma de hablar? Por que no decir directamente denir
una funcion? Ya veras dentro de poco que realmente no es una forma de hablar...
es la forma que tiene Scheme de funcionar.
1. Programacion Funcional 9
Identicador Valor
pi 3 1415
Por ejemplo, para evaluar (+ 2 3), Scheme evalua el 3 (resulta el numero 3), despues
el 2 (resulta el numero 2) y despues el + (resulta el procedimiento suma, que el
interprete representa como "#[...]"). Y por ultimo, aplica el procedimiento suma a 3 y
2, resultando 5.
10 1.2. Introduccion a Scheme
Puede parecer raro eso de que se evalue el +. Que signica eso? Pues que en Scheme
los procedimientos son objetos primitivos del mismo nivel que otros objetos como enteros
o caracteres. Ya veremos en el tema 3 que en Scheme es posible pasar un procedimiento
como parametro o incluso hacer que una funcion devuelva un procedimiento.
Los parentesis signican algo. En Scheme no puedes usar parentesis a menos que vayas
a llamar a una funcion o a una forma especial. Por ejemplo, si tecleas:
(+ ( s q u a r e 2 ) ( 3 ) )
Ejemplos:
( define ( square x )
( x x )) ; ; o d e f i n i c i n de una o f u n c i n
( square 5) ; ; l l a m a d a a l a o f u n c i n
( square (+ 2 3)) ; ; o c o m p o s i c i n con f u n c i o n e s d e f i n i d a s
1.2.4. Quote
La forma especial quote devuelve el identicador que se le pasa como argumento sin
evaluar, como el mismo identicador:
> ( quote hola )
hola
> hola
hola
La tilde () es una abreviatura de quote. Las dos expresiones anteriores son identicas.
A quote se le puede pasar como argumento un identicador o una expresion:
> ( quote ( + 1 2 ) )
(+ 1 2)
1. Programacion Funcional 11
Algunas consideraciones:
Aunque para Scheme un identicador (hello) no es exactamente igual
que un string ("hello"), muchas funciones de las anteriores las conside-
ran iguales
Muchas funciones son polimorcas: pueden usarse con distintos tipos de
objetos.
Este sencillo plural funciona correctamente (en ingles) para la mayora de las pal-
abras (book, elephant, computer) pero no para las palabras que terminan en y. Vamos a
mejorarlo:
( define ( plural wd )
( i f ( equal ? ( l a s t wd ) y )
( word ( b l wd ) i e s )
( word wd s )))
12 1.3. Programacion Funcional
( d e f i n e ( pldone ? wd )
( v o w e l ? ( f i r s t wd ) ) )
( d e f i n e ( vowel ? l e t t e r )
(member ? l e t t e r ( a e i o u ) ) )
Pigl introduce recursion una funcion que se llama a ella misma . Veremos mas sobre
esto en las proximas semanas.
(Otro ejemplo): Sabes jugar a Buzz? Comienzas a contar y si tu numero es divisible
por 7 o tiene el dgito 7 tienes que decir "buzz" en lugar del numero:
( d e f i n e ( buzz n )
( cond ( ( equal ? ( r e m a i n d e r n 7 ) 0 ) buz z )
( ( member ? 7 n ) b u z z )
( else n )))
Esto introduce la forma especial cond para multiples opciones. La forma especial cond
es la gran excepcion a la regla sobre el signicado de los parentesis; las clausulas no son
llamadas.
1.2.7. Resumen
El define es el modo de abstraccion mas sencillo en Scheme, ya has visto que permite
utilizar simples nombres para referirse a resultados de funciones compuestas, como es el
caso de la circunferencia.
En general, los objetos pueden tener estructuras muy complejas y sera muy tedioso si
tuviesemos que recordar y repetir sus detalles cada vez que queremos utilizarlos. Ademas,
los programas complejos se generan construyendo, paso a paso, objetos cada vez mas
complejos.
Asociar valores con smbolos y despues reutilizarlos, signica que debe existir algun
tipo de memoria que guarde las parejas nombre-objeto. Ese tipo de memoria se denomina
entorno (y mas concretamente, entorno global). En temas posteriores veremos que una
ejecucion puede involucrar diferentes entornos.
efectos colaterales, y ademas cada funcion siempre devuelve el mismo resultado para un
mismo parametro. Por ejemplo,
( square 2)
4
( square 2)
4
count = g e t C o u n t ( 1 0 ) ; // devuelve 10
count = g e t C o u n t ( 1 0 ) ; // devuelve 20
Fjate que si llamamos a getCount dos veces se obtienen resultados distintos. Ademas
hay un efecto colateral despues de llamar a getCount: el valor de la variable iCount vara.
Resumiendo, el Paradigma de la Programacion Funcional tiene las siguientes carac-
tersticas:
Una funcion puede tener cualquier numero de argumentos, incluyendo cero, pero
siempre debe devolver un unico valor. (Supongamos que necesitamos dos. Podramos
combinarlos en uno, por ejemplo, una frase). No es una funcion a no ser que siempre
obtengas la misma respuesta para los mismos argumentos
Y ahora vamos a ver que ocurre cuando ejecutamos (f (+ 2 1)) utilizando el modelo
de sustitucion:
7. Y (+ 36 1)? 37
1. Programacion Funcional 15
4. Por ultimo, expandimos todo los operadores primitivos y autoevaluamos los valores.
Se hace uno por uno
(+ ( (+ 3 (+ 2 1)) (+ (+ 2 1) (+ 2 1))) 1)
(+ ( (+ 3 3) (+ (+ 2 1) (+ 2 1))) 1)
(+ ( (+ 3 3) (+ 3 (+ 2 1))) 1)
(+ ( (+ 3 3) (+ 3 3))) 1)
(+ ( 6 (+ 3 3)) 1)
(+ ( 6 6) 1)
(+ 36 1)
37
Hemos visto las dos formas de evaluacion: con el orden aplicativo, evaluamos comple-
tamente todas las subexpresiones antes de aplicar el procedimiento principal. Mientras
que en el orden normal, primero expandimos completamente los procedimientos hasta
que todo esta expresado mediante operaciones primitivas y autoevaluaciones. Entonces,
en uno y en otro, podemos encontrar la solucion de la expresion.
En programacion funcional, el orden normal y el orden aplicativo siempre devolveran
el mismo resultado.
Vamos a denir una funcion que debera devolver siempre 0:
( d ef i n e ( zero x ) ( x x ) ) ; Esta funcion siempre d eb er i a d ev ol v er 0
Ahora vamos a evaluar (zero (random 10)) con orden aplicativo y con orden normal.
16 1.4. Modelo de sustitucion
Orden aplicativo
( z e r o ( random 1 0 ) )
( random 10) == > 5
( z e r o 5) >
( 5 5) == > 0
0 ; E l o r d e n de a p l i c a c i o n d e v u e l v e 0
Orden normal
( z e r o ( random 1 0 ) )
( z e r o ( random 10)) >
( ( random 1 0 ) ( random 1 0 ) )
( random 10) == > 4
( random 10) == > 8
( 4 8) == > 4
4 ; E l o r d e n norma l no
La regla es que si estas haciendo programacion funcional, obtienes las mismas re-
spuestas sea cual sea el orden de evaluacion. Por que no sucede as en el caso de (zero
(random 10))? Porque no es una funcion. Por que?
Eciencia: intenta computar
( square ( square (+ 2 3)))
2.1. Recursion
En este tema vamos a hablar de la recursion. Como disenar un algoritmo recursivo?
El consejo mas importante es el que aparece en el siguiente recuadro:
CONFIA EN LA RECURSION
CONFIAR EN LA RECURSION para resolver una version mas simple del problema
Obtener la solucion al problema completo a partir de la solucion de la version mas
simple
17
18 2.1. Recursion
Otro ejemplo. Veamos el problema de contar el numero de veces que un caracter (por
ejemplo la a) aparece en una cadena:
2. Llamamos a la recursion con el resto de la cadena (un problema mas sencillo, porque
es una cadena mas corta). Esta llamada nos dice que en el resto de la cadena hay n
letras a.
3. Si el primer caracter que hemos quitado es una a devolvemos n+1, sino devolvemos
n.
Otro problema: Pig Latin. Pig Latin es una modicacion del ingles que usan los
ninos para hablar de forma divertida. Se trata de modicar una cadena moviendo todas
las consonantes (hasta la primera vocal) de su comienzo a su nal y anadiendo el sujo
ay. Por ejemplo, en castellano:
Aqu la solucion recursiva es algo mas complicada. La primera idea sera hacerlo como
los ejemplos anteriores:
3. Caso base: si la cadena empieza por vocal devolver la cadena con el sujo ay
anadido.
Funciona bien esta solucion? Veamos un ejemplo. Apliquemos Pig Latin a la palabra
"problema". Nos debera devolver oblemapray. Sin embargo, el algoritmo anterior hara
lo siguiente:
2. Recursion 19
Como habra que plantear la recursion? Si nos jamos en el ejemplo, nos daremos
cuenta de que la "p" debera estar antes del sujo ay. Esto se consigue llamando a la
recursiondespues de haber movido la consonante al nal de la cadena:
La solucion en Scheme:
( d e f i n e ( p i g l wd )
( i f ( v o c a l ? ( f i r s t wd ) )
( word wd ay )
( p i g l ( word ( b f wd ) ( f i r s t wd ) ) ) ) )
Donde esta aqu la regla general? Estamos aplicando la recursion a un caso mas
sencillo? S, ya que la palabra roblemap tiene la primera vocal mas a la izquierda que
problema.
No todas las recursiones siguen este patron. En los ejemplos anteriores en el cuerpo de
la funcion se realiza una unica llamada recursiva. No siempre es as. Por ejemplo, veamos
el calculo de la serie de Fibonacci. Recordemos que la secuencia de numeros de Fibonacci
se dene con la siguiente expresion:
1, si n {0, 1}
f ib(n) =
f ib(n 1) + f ib(n 2), si n > 1
De esta forma, la secuencia de numeros de Fibonacci es: 1, 1, 2, 3, 5, 8, 13, 21, . . . La
funcion recursiva que calcula el numero n-esimo de la serie es la siguiente:
( define ( f ib n)
( cond ( ( = n 0 ) 0 )
((= n 1 ) 1 )
( e l s e (+ ( f i b ( n 1 ) )
( f i b ( n 2 ) ) ) ) ) )
La diferencia con las funciones recursivas vistas hasta ahora es que en el cuerpo de la
funcion se realizan dos llamadas recursivas. Esto genera un proceso recursivo en forma de
arbol, como se comprueba en la siguiente gura, extrada del Abelson & Sussman.
20 2.2. Procesos recursivos e iterativos
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
..
.
La funcion Scheme que calcula el numero de Pascal que se encuentra en una determi-
nada la y columna es la siguiente:
( d e f i n e ( p a s c a l row c o l )
( cond ( ( = c o l 0 ) 1 )
((= c o l row ) 1 )
( e l s e ( + ( p a s c a l (1+ row ) (1+ c o l ) )
( p a s c a l (1+ row ) c o l ) ) ) ) )
El proceso que genera esta funcion es un proceso que tambien tiene forma de arbol,
ya que se hacen dos llamadas recursivas dentro del cuerpo de la funcion.
( d e f i n e ( count s e n t )
( i f ( empty ? s e n t )
0
(1+ ( count ( b f s e n t ) ) ) ) )
Esta vez, no dejamos ninguna computacion en espera, no tenemos que recordar tareas
no completas; cuando alcanzamos el caso base de la recursion tenemos la respuesta al
22 2.2. Procesos recursivos e iterativos
problema completo.
( count a b c d e f )
( i t e r abcdef 0)
( i t e r bcdef 1)
( i t e r cdef 2)
( i t e r def 3)
( i t e r ef 4)
( i t e r f 5)
( i t e r 6 )
6
2.2.1. Factorial
; ; f a c t o r i a l proceso re c ur s i v o
( define ( f a c t o r i a l n)
( i f (= n 1)
1
( n ( f a c t o r i a l ( n 1 ) ) ) ) )
; ; f a c t o r i a l proceso i n t e r a t i v o
( define ( f a c t o r i a l n)
( factiter 1 1 n ))
( d e f i n e ( f a c t i t e r p r o d u c t c o u n t e r maxcount )
( i f ( > c o u n t e r maxcount )
product
( f a c t i t e r ( counter product )
(+ c o u n t e r 1 )
maxcount ) ) )
2. Recursion 23
( define ( f ib n)
( cond ( ( = n 0 ) 0 )
((= n 1 ) 1 )
( e l s e (+ ( f i b ( n 1 ) )
( f i b ( n 2 ) ) ) ) ) )
; ; proceso i t e r a t i v o
( define ( f ib n)
( fibiter 1 0 n ))
( d e f i n e ( f i b i t e r a b count )
( i f ( = count 0 )
b
( f i b i t e r ( + a b ) a ( count 1 ) ) ) )
24 2.2. Procesos recursivos e iterativos
Tema 3
Procedimientos de orden superior
25
26 3.1. Funciones como datos de primera clase
( define pi 3.141592654)
( define ( squarearea r ) ( r r ))
( define ( circlearea r ) ( pi r r ))
( define ( spherearea r ) ( 4 pi r r ))
( define ( hexa gon a r ea r ) ( ( s q r t 3 ) 1 . 5 r r ) )
Hemos denido nombres para las formas; cada nombre representa un numero constante
que se multiplica por el cuadrado del radio. Estamos generalizando un patron mediante
el uso de un numero variable en lugar de un numero constante.
Pero tambien podemos genealizar un patron en el que lo que vara es una funcion.
Veamos los dos ejemplos siguientes:
( d e f i n e ( s ums qua re a b )
( i f (> a b)
0
( + ( a a ) ( sumsquare ( 1 + a ) b ) ) ) )
( d e f i n e ( sumcube a b )
( i f (> a b)
0
( + ( a a a ) ( sumcube ( 1 + a ) b ) ) ) )
Cada una de estas funciones calcula la suma de una serie desde un numero inicial (a)
hasta un numero nal (b). Por ejemplo (sumsquare 5 8) calcula 52 + 62 + 72 + 82 . El
proceso de calcular cada termino indvidual, de anadir los terminos, y de saber cuando
parar es el mismo estemos anadiendo cuadrados de numeros o cubos de numeros. La unica
diferencia esta en decidir que funcion aplicar a cada termino. Podemos generalizar este
patron haciendo que la funcion sea un argumento adicional, de la misma forma que el
argumento number en la funcion area:
3. Procedimientos de orden superior 27
( d e f i n e ( sum f n a b )
( i f (> a b)
0
(+ ( f n a ) ( sum f n ( 1 + a ) b ) ) ) )
3.2. Let
Let es una forma especial de Scheme que permite llamar a una expresion (el cuerpo
del let) despues de haber declarado unos valores para unas variables que se usan en esta
expresion. Esta declaracion de valores es local a la ejecucion del let. Una vez que la
expresion del let se evalua, no se conservan esos valores. Su sintaxis es:
( l e t ( ( v a r 1 exp1 )
...
( v a r n expn ) )
)
Para evaluar el let, las expresiones exp1 . . . expn se evaluan y sus valores se asocian a
las variables var1 . . . varn . La expresion se evalua con estos valores asignados. Ejemplos:
> ( let (( x 1)
(y 2))
(+ x y ) )
3
> ( define x 5)
> ( let (( x (+ 2 1))
( y (+ x 3 ) )
(+ x y ) )
11
Dos precauciones:
1. Let no proporciona una sentencia de asignacion tal y como existen en otros lengua-
jes. La asociacion entre los nombres y los valores solo se mantienen mientras que
computamos el cuerpo del let.
28 3.2. Let
2. Si tienes mas de una pareja nombre-valor, como en este ultimo ejemplo, los calculos
no se realizan secuencialmente. Las ultimas asociaciones no dependen de las previas.
Vamos a aclarar esto ultimo explicando como se dene let en terminos de lambda:
( l e t ( ( v a r 1 exp1 )
...
( v a r n expn ) )
)
se traduce a
Esto es, se construye una funcion sin nombre con los mismos argumentos del let y se
llama a esa funcion con el resultado de evaluar las expresiones asociadas a cada argumento.
Por ejemplo:
( let (( x 1)
(y 4))
( x y ))
se traduce a
( ( lambda ( x y )
( x y )) 1 4)