Departamento de Electrnica e Informtica, Universidad Centroamericana Jos Simen Caas
Programando con Racket 5por
Eduardo NAVASversin 1.0 2010.07.21
Este libro fue desarrollado nicamente con software libre. Entre las herramientas usadas,
AT X, L X, GNU/Linux, GNOME, KDE, KmPlot, GIMP, Python, etc. se encuentran: L E Y
CC-BY-NC-SAEste es un libro libre con la licencia
Creative Commons Attribution-Noncommercial-Share Alike 3.0.Los detalles pueden ser consultados en: http://creativecommons.org/licenses/by-nc-sa/3.0/deed.es La versin digital y el material adicional puede ser descargado de: www.aliamondano-eo.wikidot.com/racket-5 http://dei.uca.edu.sv/publicaciones/ ISBN: 978-99923-73-61-3 Editado y preparado desde el
Departamento de Electrnica e InfomticaEl Salvador, Centroamrica.
de la
Universidad Centroamericana Jos Simen Caas,
Dedico esta obra al egosmo
PrlogoEste libro evolucion a partir del material preparado para las clases de la materia Programacin Funcional, impartida para la Carrera de Licenciatura en Ciencias de la Computacin de la Universidad Centroamericana Jos Simen Caas. Despus de un ao de trabajo, este libro incluye un recorrido por las caractersticas bsicas del lenguaje Racket, en su versin 5.
Racket 5
es la nueva versin de
PLT Scheme, un sistema de programacin de larga tradicin
en el aprendizaje de la programacin de computadoras, a travs del paradigma funcional, basndose en el lenguaje Scheme. Realmente no existe, formalmente hablando, un lenguaje llamado Scheme, sino que se le llama as a una familia de lenguajes de programacin funcionales (vase el captulo 1). En este libro, se discute especcamente el dialecto conocido como Racket (anteriormente PLT Scheme), uno de los ms difundidos. Si se quiere un estudio ms purista sobre Scheme, revise el estndar R5RS que tambin es soportado por el intrprete de Racket. Los temas abordados en la Parte I incluyen una introduccin a la programacin funcional, una sencilla gua de instalacin de Racket y una introduccin a la interaccin con Racket y DrRacket. En la Parte II se introduce el lenguaje Racket en s, a travs de sus elementos bsicos y los bloques lambda, caractersticos de la programacin funcional. La Parte III describe los dems elementos del lenguaje y contiene mltiples ejercicios para que el lector practique sus nuevos conocimientos. Finalmente, la Parte IV muestra las capacidades de Racket para implementar programas con interfaces gracas de usuario. Y por ltimo, la Parte V incluye un anexo describiendo las diferencias entre la versin 5 de Racket y la serie 4.x de PLT Scheme.
7
8
ndice generalI. Introduccin a la Programacin Funcional con Racket1. Programacin Funcional1.1. 1.2. 1.3. 1.4. Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Caractersticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lenguajes de Programacin Funcionales
171919 20 20 21
Ejemplos de cdigo de lenguajes funcionales . . . . . . . . . . . . . . . . . .
2. Instalacin de Racket2.1. 2.2. Instalacin con el instalador ocial Instalacin desde repositorios 2.2.1. 2.2.2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fedora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2323 24 24 25
3. Expresiones Racket - Notacin Preja3.1. 3.2. Notacin para la sintaxis de Racket . . . . . . . . . . . . . . . . . . . . . . . Notacin preja de Racket . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2727 27
4. Interaccin con Racket4.1. Ejecucin interactiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1. 4.1.2. 4.2. 4.2.1. Deniciones e interacciones con DrRacket Ejecucin interactiva con Racket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2929 30 30 31 31
Ejecucin no interactiva
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Parmetros de la lnea de comandos
5. Compilacin de programas Racket5.1. 5.2. Lo bsico sobre compilacin . . . . . . . . . . . . . . . . . . . . . . . . . . . Compilacin con mltiples mdulos . . . . . . . . . . . . . . . . . . . . . . .
3333 33
II. Introduccin al lenguaje Racket6. Elementos bsicos6.1. Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
353737
9
ndice general6.2. Deniciones Globales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1. 6.3. 6.4. Identicadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 38 39 39 39 40 41 42 43 43
Llamadas a funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bloques condicionales 6.4.1. 6.4.2. 6.4.3. 6.4.4. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
if . . . nd y or ond . . se . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.5. 6.6.
Bloques de cdigo secuencial . . . . . . . . . . . . . . . . . . . . . . . . . . . Ms sobre llamadas a funciones . . . . . . . . . . . . . . . . . . . . . . . . .
7. Funciones annimas - Bloques lmd7.1. 7.2. Bloques
lmd
4545 46 . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Funciones/Expresiones que producen funciones
8. Asignacin local8.1. 8.2. 8.3.
define let . . letB .
4949 50 50
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
III. Elementos del lenguaje9. Listas e Iteracin9.1. Listas 9.1.1. 9.1.2. 9.2. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Lista vaca o nula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Funciones bsicas sobre listas . . . . . . . . . . . . . . . . . . . . . .
515353 54 54 56 56 56 57 58 59 59 60 61 62 62
Iteracin automtica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1. 9.2.2. 9.2.3. 9.2.4. 9.2.5.
mp . . . . . . . ndmp y ormp filter . . . . . forEeh . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Versiones generales de las funciones de iteracin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.3.
Iteracin manual 9.3.1.
Aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.4.
Pares y listas 9.4.1. 9.4.2.
Convencin de impresin . . . . . . . . . . . . . . . . . . . . . . . . . Notacin inja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.Recursin10.1. Recursin por Posposicin de trabajo . . . . . . . . . . . . . . . . . . . . . . 10.2. Recursin de Cola . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6767 67
10
ndice general
11.Tipos de dato integrados del lenguaje11.1. Booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2. Nmeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1. Clasicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Clasicacin por Exactitud Clasicacin por Conjuntos 11.2.2. Otras bases 11.2.3. Comparaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6969 70 70 70 72 72 73 73 74 76 77 78 79 80 81 83 83 84 85 86
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.2.4. Constantes especiales . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3. Caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.1. Cadenas mutables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.4.2. Comparacin entre cadenas
11.4.3. Otras funciones de cadena . . . . . . . . . . . . . . . . . . . . . . . . 11.5. Bytes y Cadenas de Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.6. Smbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.7. Palabras clave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.8. Pares y listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.9. Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.10. Tablas Hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.11. Void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.Expresiones y Deniciones Avanzadas12.1. La funcin 12.2. Bloques
pply lmd .
8989 89 90 90 91 92 93 94 94 94 95 96 97 97 97 98 . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.2.1. Funciones con cualquier nmero de parmetros 12.2.2. Funciones con un mnimo nmero de parmetros 12.2.4. Funciones con parmetros con nombre
12.2.3. Funciones con parmetros opcionales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.5. Funciones con aridad mltiple . . . . . . . . . . . . . . . . . . . . . . 12.2.6. Consultando la aridad de las funciones . . . . . . . . . . . . . . . . .
rityEtElest . . . . . . . proedureErity . . . . . . . proedureErityEinludesc12.3.1. 12.3.2. 12.3.3.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.3. Resultados mltiples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
vlues . . . . . . . . . . . . defineEvlues . . . . . . . letEvlues, y letBEvlues
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12.4. Asignaciones
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13.Tipos de dato denidos por el programador13.1. Estructuras simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
101101
11
ndice general13.2. Estructuras derivadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 104 104
13.3. Estructuras transparentes y opacas . . . . . . . . . . . . . . . . . . . . . . . 13.4. Estructuras mutables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.Mdulos Funcionales14.1. Visibilizando deniciones de estructuras . . . . . . . . . . . . . . . . . . . .
109110
15.Entrada y Salida15.1. Imprimir datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2. Leer datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.2.1. Lectura "bsica" . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
111111 113 113 114 115 116 116 116 117 117 118 119 120 122
15.2.2. Lectura avanzada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3. Tipos de Puerto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3.1. Archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
openEinputEfile . . . . . openEoutputEfile . . . . openEinputEoutputEfile
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Procesamiento automatizado . . . . . . . . . . . . . . . . . . . . . .
15.3.2. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3.3. Conexiones TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15.4. Puertos de Entrada/Salida por defecto . . . . . . . . . . . . . . . . . . . . .
16.Excepciones16.1. Atrapar Excepciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.2. Las funciones error y raise . . . . . . . . . . . . . . . . . . . . . . . . . . . .
127127 128
17.Evaluacin Dinmica de Cdigo17.1. La funcin
evl
131131 132 . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17.2. Creacin y ejecucin dinmica de cdigo fuente
18.Programacin Orientada a Objetos18.1. Denicin de Clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.2. Denicin de Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.3. Creacin de instancias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
133133 133 133 134 134 134 135 135 136 137
18.4. Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.4.1. Denicin e Invocacin de Mtodos . . . . . . . . . . . . . . . . . . . 18.4.2. Sustitucin de mtodos 18.4.3. Mtodos no sustitubles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18.5. Parmetros de inicializacin . . . . . . . . . . . . . . . . . . . . . . . . . . . 18.6. Funciones que operan sobre clases/interfaces/objetos . . . . . . . . . . . . . 18.7. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
12
ndice general
IV. Interfaces Grcas de Usuario19.Introduccin a las interfaces grcas de usuario con Racket19.1. Hola Mundo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2. Ejecucin y compilacin 19.4. Ventanas de dilogo 19.6. Pneles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.3. Introduccin a los eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.5. Eventos de cuadros de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
141143143 144 144 147 148 150
20.Uso de los diversos controles de Racket 21.Dibujo con Lienzos21.1. Dibujo en un
153 163163 165
nvs 7
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21.2. Interaccin avanzada con
nvs 7
. . . . . . . . . . . . . . . . . . . . . . .
22.Mens22.1. Ejemplo de editor sencillo de texto . . . . . . . . . . . . . . . . . . . . . . . 22.2. Mens contextuales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
171174 177
23.Proyecto: Minipaint
183
V. ApndicesA. Diferencias entre PLT Scheme y Racket
197199
13
ndice general
14
ndice de guras2.1. Sitio de descarga de Racket . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
6.1.
Grca de ecuacin seccionada
x < 1 x + 2 f (x) = 1 1 x < 0 2 x + 1 0 x
. . . . . . .
41
19.1. hola-mundo.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.2. eventos-1.rkt 19.3. eventos-2.rkt 19.4. eventos-3.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
143 144 145 146 147 148 150 153 153 154 155 156 157 158 163 165 167 169 171 172 173 175 179 180 181
19.5. dialogo.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.6. text-eld.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19.7. pneles.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.1. controles.rkt, tab 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.2. controles.rkt, tab 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.3. controles.rkt, tab 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.4. controles.rkt, tab 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.5. controles.rkt, tab 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.6. controles.rkt, tab 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20.7. controles.rkt, tab 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1. canvas1.rkt 21.2. canvas2.rkt 21.3. canvas3.rkt 21.4. canvas4.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
22.1. Diagrama de clases de los mens en Racket
22.2. Diagrama de objetos del ejemplo 1-mens.rkt
22.3. 1-mens.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.4. 2-mens.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22.5. 5-seleccin-color.rkt - men . . . . . . . . . . . . . . . . . . . . . . . . . . .
22.6. 5-seleccin-color.rkt - Selector de color 1 . . . . . . . . . . . . . . . . . . . . 22.7. 5-seleccin-color.rkt- Selector de color 2 . . . . . . . . . . . . . . . . . . . .
15
ndice de guras23.1. mini-paint.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
16
Parte I
Introduccin a la Programacin Funcional con Racket
17
1 Programacin FuncionalLa programacin funcional, iniciada a nales de la dcada de los 50's, es aquella cuyo paradigma se centra en el Clculo Lambda. Este paradigma es ms til para el rea de inteligencia articial (ya que satisface mejor las necesidades de los investigadores en esta rea), y en sus campos secundarios: clculo simblico, pruebas de teoremas, sistemas basados en reglas y procesamiento del lenguaje natural. La caracterstica esencial de la programacin funcional es que los clculos se ven como una funcin matemtica que hace corresponder entradas y salidas.
1.1. ObjetivoEl objetivo es conseguir lenguajes expresivos y matemticamente elegantes, en los que no sea necesario bajar al nivel de la mquina para describir el proceso llevado a cabo por el programa, y evitando el concepto de estado del cmputo. Los lenguajes funcionales tienen el propsito de acercar su notacin a la notacin normal de la matemtica, cosa que no ocurre, por ejemplo, con los lenguajes imperativos (como
C
o
Java ).
El estado de cmputo o estado de clculo o estado de programa, se entiende como un registro (con una o ms variables) del estado en el que se encuentra el programa en un momento dado. En la prctica, este registro del estado de un programa, se implementa con variables globales, de las que depende el curso de ejecucin de alguna parte del programa. Por ejemplo, considere el siguiente cdigo en lenguaje
C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Archivo : no - funcional . c # include < stdio .h > int variable_contador = 0; int aumentar_contador ( int incremento ) { variable_contador += incremento ; return variable_contador ; } void mostrar_contador ( void ) { printf ( " El valor del contador es : %d \ n " , variable_contador ) ; }
19
1 Programacin Funcional15 16 17 18 19 20 21 22
int main ( void ) { mostrar_contador () ; aumentar_contador (5) ; mostrar_contador () ; aumentar_contador (10) ; mostrar_contador () ; return 0; }En este pequeo programa, se puede decir que programa.
vrileontdor representa el estado del
1.2. CaractersticasLos programas escritos en un lenguaje funcional estn constituidos nicamente por deniciones de funciones, entendiendo stas, no como subprogramas clsicos de un lenguaje imperativo, sino como funciones puramente matemticas, en las que se verican ciertas propiedades como la
transparencia referencial. La transparencia referencial, signica que el signicado de una expresin depende nicamente del signicado de sus subexpresiones o parmetros, no depende de clculos previos ni del orden de evaluacin de sus parmetros o subexpresiones, y por tanto, implica la carencia total de efectos colaterales. No hay algo como el estado de un programa, no hay variables globales. En el caso del programa
noEfunionlF,
presentado arriba, el resultado de la expresin
no slo depende del nmero
IH,
sino de otra variable ajena a la funcin.
Otras caractersticas propias de estos lenguajes (consecuencia directa de la ausencia de estado de cmputo y de la transparencia referencial) son la no existencia de asignaciones de variables y la falta de construcciones estructuradas como la secuencia o la iteracin (no hay
for, ni while, etc.). Esto obliga en la prctica, a que todas las repeticiones de instruccionesse lleven a cabo por medio de funciones recursivas.
1.3. Lenguajes de Programacin FuncionalesExisten dos grandes categoras de lenguajes funcionales: los funcionales puros y los funcionales hbridos. La diferencia entre ambos radica en que los lenguajes funcionales hbridos son menos dogmticos que los puros, al incluir conceptos tomados de los lenguajes imperativos, como las secuencias de instrucciones o la asignacin de variables. En contraste, los lenguajes funcionales puros tienen una mayor potencia expresiva, conservando a la vez su transparencia referencial, algo que no se cumple siempre con un lenguaje funcional hbrido. Sin embargo, es de mencionar que en un lenguaje de programacin funcional puro, en la prctica, sera muy difcil programar sistemas; aunque son muy buenos para aplicaciones eminentemente matemticas.
20
1.4 Ejemplos de cdigo de lenguajes funcionalesEntre los lenguajes funcionales puros, cabe destacar a Haskell y Miranda. Los lenguajes funcionales hbridos ms conocidos son Lisp, los dialectos de Scheme y Ocaml. Erlang es un lenguaje funcional de programacin concurrente. R es un lenguaje funcional dedicado a la estadstica. Mathematica y Maxima son tambin lenguajes/entornos funcionales, orientados totalmente al lgebra simblica. Entre otros lenguajes que se podran utilizar para programacin funcional, se podran incluir a Perl, usando exclusivamente funciones denidas por el usuario. As como Python, como lenguaje que incorpora el paradigma funcional.
1.4. Ejemplos de cdigo de lenguajes funcionalesEn Haskell:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-- Funcin recursiva para calcular el factorial de un nmero factorial :: Integer -> Integer factorial n = if n ==0 then 1 else n * factorial ( n - 1) -- Sumar elementos de una lista sumar :: [ Integer ] -> Integer sumar [] = 0 sumar ( x : xs ) = x + sumar ( xs ) -- Funcin para calcular el valor de e (2.71828182845905) euler :: Double -> Double euler 0.0 = 1.0 euler n = 1.0 / product [1.. n ] + euler ( n - 1.0)En Miranda:
1 2
|| Lista de cuadrados de n donde n es tomado de la lista de todos los enteros positivos : squares = [ n * n | n 0 | x :: xs -> 1 + long xs ;;En Erlang:
1 2
fac (0) -> 1; fac ( N ) when N > 0 -> N * fac (N -1) .
21
1 Programacin FuncionalEn Python:
1 2 3 4 5 6 7 8 9 10 11 12
>>> vec = [2 , 4 , 6] >>> [3* x for x in vec ] [6 , 12 , 18] >>> [3* x for x in vec if x > 3] [12 , 18] >>> [[ x , x **2] for x in vec ] [[2 , 4] , [4 , 16] , [6 , 36]] >>> >>> >>> [8 , vec1 = [2 , 4 , 6] vec2 = [4 , 3 , -9] [ x * y for x in vec1 for y in vec2 ] 6 , -18 , 16 , 12 , -36 , 24 , 18 , -54]
22
2 Instalacin de Racket2.1. Instalacin con el instalador ocialA continuacin de describen los pasos bsicos de instalacin: 1. Vaya al sitio http://racket-lang.org/download/ y descargue el instalador correspondiente o ms cercano a su distribucin, tal como se muestra en la gura 2.1. 2. El archivo descargado es un
.sh, por lo que hay que asignarle los permisos de ejecucin,1
necesarios para poder ejecutarlo :
6 hmod uCx rketExxxxFsh 6 FGrketExxxxFsh3. A continuacin, el instalador pregunta si se desea hacer una instalacin tipo Unix o una instalacin en una sla carpeta. La opcin por defecto es no hacer una instalacin tipo Unix. 4. Luego se pregunta en cul carpeta se desea realizar la instalacin (en caso de haber respondido no en el paso anterior. La opcin por defecto es del usuario o en cualquier otra. 5. A continuacin se procede a realizar la instalacin en la carpeta elegida y aqu termina la instalacin. Automticamente se instalan las pginas de la documentacin ocial de Racket en la carpeta de instalacin elegida. Si la carpeta de instalacin elegida no fue en la carpeta del usuario, es muy probable que la carpeta de la documentacin sea
GusrGplt,
para la cual
se requiere tener permisos de superusuario. Tambin se puede instalar en la carpeta
GusrGshreGdoGplt, 6 ro dos
o
GusrGpltGdoG.
En esta carpeta habr un archivo
GusrGshreGplt, indexFhtml.
En todo caso, con el comando se lanza la pgina del ndice de la documentacin instalada con el navegador por defecto del Sistema Operativo.
1
o simplemente ejecutar:$ sh racket-xxxx.sh
23
2 Instalacin de Racket
Figura 2.1: Sitio de descarga de Racket
2.2. Instalacin desde repositoriosPor el momento , las distribuciones de GNU/Linux no incluyen la nueva versin (la 5.0) de
2
Racket.
En su lugar, todava incluyen la serie 4.x de
compatible con todo el contenido de este libro , en esta primera versin). Es slo cuestin
3
PLT Scheme
(que es completamente llamada
PLT Scheme, Racket, se encuentre en los repositorios de las distribuciones ms difundidas.de tiempo (unos 6 meses o un ao) para que la nueva versin de distribucin de GNU/Linux que contiene a
El proceso de instalacin es en general muy sencillo. Especialmente cuando usamos una
PLT Scheme
en sus repositorios.
2.2.1. DebianEn distribuciones basadas en
5 ptEget instll pltEsheme
Debian, basta con instalar el paquete pltEsheme:pltEshemeEdo que instala la documentacin
Tambin sera buena idea, instalar el paquete pgina
ocial de la versin instalada por el paquete anterior. Con este paquete, est disponible la
GusrGshreGpltGdoGindexFhtml
que es el ndice de la documentacin.
2 3
Al momento de escribir este libro vase el apndice A
24
2.2 Instalacin desde repositoriosPara instalar la documentacin junto con el programa, ejecute el siguiente comando:
5 ptEget instll pltEsheme pltEshemeEdo
2.2.2. FedoraEn distribuciones
5 yum instll pltEsheme
Fedora, basta con instalar el paquete pltEsheme:
En esta distribucin no se encuentra la documentacin como paquete, por lo que hay que consultarla en lnea, o descargarla.
25
2 Instalacin de Racket
26
3 Expresiones Racket - Notacin Preja3.1. Notacin para la sintaxis de RacketDesde este momento en adelante, se utilizar la siguiente notacin tipo BNF para explicar la sintaxis del lenguaje: Todas las secuencias de caracteres delimitadas por terminales. Por ejemplo:
`smolonoterminlb.
`
y
b
representan smbolos no
Todas las secuencias de caracteres no delimitadas, representan smbolos terminales. Por ejemplo:
define, @, A, let. {y
El metaagrupamiento se hace con llaves: El metasmbolo El metasmbolo
}.
C, B,
indica al menos una ocurrencia del smbolo precedente. indica ninguna, una o varias ocurrencias del smbolo precedente.
3.2. Notacin preja de RacketEn Racket, todas las expresiones tienen la forma:
@`operdorb `operndobBA,
es decir,
que estn siempre en notacin preja con pareamiento completo:
@B @b @C @C
P S P R
QA Eb equivale a @P B QA TAEb equivale a @S b TA Q IHAEb equivale a @P C Q C IHA @B Q PAAEb equivale a @R C Q B PA5a + 2bc2es:
Por ejemplo, la expresin inja
@C @B S A @B P AA.
27
3 Expresiones Racket - Notacin Preja
28
4 Interaccin con RacketDependiendo de cmo se vea, Racket es: un lenguaje de programacin, una familia de lenguajes de programacin, variantes de Scheme, que a su vez, es un dialecto de Lisp; o un conjunto de herramientas de programacin. Racket tiene bsicamente dos herramientas principales:
rket,
el compilador, intrprete y sistema de ejecucin interactiva; y
DrRacket, un IDE que corre sobre cin y compilacin). En el caso de
rket
(es decir, que lo usa como motor de ejecu-
DrRacket1 , debe especicarse el lenguaje en particular que se va a utilizar, ya racket.En nuestro caso particular, usaremos la opcin Usar el lenguaje
que este Entorno se acomoda a diversas variantes de Scheme soportadas por el intrprete y compilador declarado en el cdigo fuente. Cuando se selecciona esta opcin, en el rea de texto para escribir el programa, aparece la lnea:
5lng rketEsta lnea, al inicio de cualquier archivo de texto, indica que el cdigo a continuacin, es la variante ms completa (en trminos de bibliotecas disponibles y capacidad del lenguaje) de todas las variantes soportadas por Racket, conocido como
Lenguaje Racket.
Cuando se ejecuta el Racket en la lnea de comandos (con el comando por omisin es esta variante.
rket),
el lenguaje
4.1. Ejecucin interactivaLa parte de abajo de la interfaz de DrRacket (comando de comandos
rket,
drrket), y la herramienta de lnea
funcionan como un rea de interacciones, al estilo de una terminal
normal. En ella, se puede escribir una expresin (aqu no hay comandos, ni instrucciones), presionar Intro y el intrprete devuelve el resultado de la expresin.
1
Para mayor informacin sobre DrRacket, lase la documentacin ocial de DrRacket.
29
4 Interaccin con RacketPor ejemplo:
1 2 3 4 5 6 7 8
> 5 5 > (+ ( sqr 4) ( sqr 3) ) 25 > " Hola Mundo !" " Hola Mundo !" > ( substring " Hola Mundo !" 6 11) " Mundo "En la ltima expresin, se invoc a una funcin llamada una cadena, y dos nmeros enteros.
sustring,
con tres parmetros:
4.1.1. Deniciones e interacciones con DrRacketSe pueden denir funciones propias, basndose en otras funciones como
sustring.
Para
ello, en el rea de deniciones (el rea de texto superior) se escribe algo como:
1 2 3 4 5 6
# lang racket ; extraer . rkt ( define ( extraer str ) ( substring str 4 7) )Presionar el botn Run y luego, en el rea de interacciones (la terminal de abajo), ya se puede invocar esa funcin:
1 2 3 4
> ( extraer "1234567890") "567" > ( extraer " este es un texto con muchos caracteres ") " es "
4.1.2. Ejecucin interactiva con RacketPara poder hacer esto mismo con
rket,
primero hay que guardar las deniciones en un
archivo (por convencin, con extensin
.rkt), por ejemplo en un archivo llamado extrerFrkt.
Entonces, en la lnea de comandos, hacemos:
1 2 3
> ( enter ! " extraer . rkt ") > ( extraer "1234567890") "567"La funcin
enter3
carga el archivo pasado como parmetro y cambia el contexto de evalu-
acin a las deniciones del archivo, igual que el botn Run de DrRacket.
30
4.2 Ejecucin no interactiva
4.2. Ejecucin no interactivaSi tiene el archivo:
1 2 3 4 5 6 7 8
# lang racket ; extraer2 . rkt ( define ( extraer str ) ( substring str 4 7) ) ( extraer "1234567890")Ese es un programa completo que imprime en pantalla Para ejecutarlo, vaya la lnea de comandos:
STU
cuando se ejecute.
1 2 3
$ racket extraer2 . rkt " 567 " $Se dice que es ejecucin no interactiva porque uno no puede invocar a voluntad funciones denidas en el archivo. Slo se ejecutan las deniciones y llamadas que se encuentran en el archivo. Sin embargo, los programas pueden ser interactivos en el sentido que el curso de la ejecucin se puede cambiar en tiempo de ejecucin.
4.2.1. Parmetros de la lnea de comandosLa ejecucin de un programa, puede controlarse, por ejemplo, con parmetros de la lnea de comandos. Esto se logra con la funcin el siguiente programa:
urrentEommndElineErguments que retorna un
vector inmutable de cadenas inmutables, una por cada parmetro. Por ejemplo, considere
1 2 3 4 5 6
# lang racket ; linea - de - comandos . rkt ( display " Los parmetros pasados al programa son : \ n ") ( write ( current - command - line - arguments ) ) ( newline )Puede ejecutarlo as:
6 rket lineEdeEomndosFrkt holD 4est es4 un prueY la salida sera:
vos prmetros psdos l progrm sonX [email protected] 4est es4 4un4 4prue4A
31
4 Interaccin con Racket
32
5 Compilacin de programas Racket5.1. Lo bsico sobre compilacinComo parte de Racket, se incluye el programa Racket. Puede obtener una breve descripcin de todas sus posiblidades con
ro que es la herramienta de compilacin de 6 ro EEhelp.
La compilacin de un programa Racket es muy sencilla. Suponga que tiene el programa:
1 2 3
# lang racket ; hola . rkt ( display " Hola Mundo !\ n ")Se compila as:
6 ro exe Eo ejeutle holFrktPara ejecutarlo, dependiendo de la conguracin de la terminal:
1 2 3
$ ./ ejecutable Hola Mundo ! $
5.2. Compilacin con mltiples mdulosEl hecho de tener un programa separado en mdulos funcionales, no afecta el proceso de compilacin. Simplemente hay que compilar el archivo que contiene la ejecucin inicial de nuestra aplicacin. Por ejemplo, considere los siguientes dos archivos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# lang racket ; principal . rkt ( require " secundario . rkt ") ( define parmetros ( current - command - line - arguments ) ) ( funcin - pblica " hola ") ( funcin - pblica constante - de - mdulo ) ( if (( vector - length parmetros ) . > . 0) ( for - each funcin - pblica ( vector - > list parmetros ) ) ( display " No se pasaron parmetros \ n ") ) ( display " Adis !\ n ")
33
5 Compilacin de programas Racket1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# lang racket ; secundario . rkt ( provide funcin - pblica constante - de - mdulo ) ( define constante - de - mdulo " Esta constante est en secundario . rkt ") ( define ( funcin - pblica parmetro ) ( funcin - privada parmetro ) ) ( define ( funcin - privada parmetro ) ( display " Esta es una funcin declarada e implementada en secundario . rkt \ n ") ( display " El parmetro pasado es : ") ( write parmetro ) ( newline ) ) " Cuando se importa un mdulo , se ejecuta como un script "Y para compilarlos, simplemente se hace:
6 ro exe Eo ejeutle priniplFrktY para ejecutar el programa:
6 FGejeutle 4otros prmetros4 unidos 4gundo se import un mduloD se ejeut omo un sript4 ist es un funin delrd e implementd en seundrioFrkt il prmetro psdo esX 4hol4 ist es un funin delrd e implementd en seundrioFrkt il prmetro psdo esX 4ist onstnte est en seundrioFrkt4 ist es un funin delrd e implementd en seundrioFrkt il prmetro psdo esX 4otros prmetros4 ist es un funin delrd e implementd en seundrioFrkt il prmetro psdo esX 4unidos4 edis3 6
34
Parte II
Introduccin al lenguaje Racket
35
6 Elementos bsicosA continuacin se presenta un recorrido por las principales y ms bsicas partes del lenguaje Racket.
6.1. ComentariosLos comentarios son elementos escenciales en todo lenguaje de programacin, ya que permiten que el programador aclare la futura lectura del cdigo fuente. En Racket, los comentarios de una lnea comienzan con delimitados por Ejemplo:
5|
y
|5.
Y
y los comentarios de bloque son
1 2 3 4 5 6 7 8
# lang racket ; Todos los programas Racket deben comenzar con esta lnea de arriba . #| Este es un comentario en Racket , que tiene varias lneas .
|# ( display " Bueno , esto no es comentario , es cdigo \ n ") ;; Esto s ; -)
6.2. Deniciones GlobalesUna denicin de la forma
@define `identifidorb `expresinbA le asigna a `identifidorb el resultado deUna denicin de la forma
evaluar
`expresinb.
@define @`identifidorb `identifidorbBA `expresinbC A le asigna al primer `identifidorb una funcin (o procedimiento) que toma tantos argumentos como `identifidorbes restantes haya dentro de los parntesis. El cuerpo de la funcin es la serie `expresinbC y cuando la funcin es llamada, devuelve el resultado de la ltima `expresinb.Ejemplo:
37
6 Elementos bsicos1 2 3 4 5 6 7 8 9 10 11 12 13
( define mximo 3) ( define ( prefijo str ) argumento ( substring str 0 mximo ) )
; Define que mximo es 3 ; Define que prefijo es una funcin de un
> mximo 3 > ( prefijo " Hola , cmo ests ?") " Hol " > prefijo # < procedure : prefijo > > substring # < procedure : substring >Una funcin puede tener mltiples expresiones, pero la funcin slo devuelve el resultado de la ltima:
1 2 3 4 5 6 7 8 9
( define ( hornear sabor ) ( printf " Precalentando el horno para ...\ n ") " Esta cadena es completamente ignorada " ( string - append " pastel de " sabor ) ) > ( hornear " manzana ") Precalentando el horno para ... " pastel de manzana "
6.2.1. IdenticadoresLos identicadores en Racket son muy liberales. A diferencia de otros lenguajes de programacin que restringen mucho los caracteres vlidos para sus identicadores, en Racket, prcticamente no hay restricciones. Los nicos caracteres no vlidos en los identicadores son:
.
@ A { } D 9 Y 5 |
Tampoco se pueden utilizar identicadores que se correspondan con literales numricos
y tampoco estn permitidos los espacios dentro de los identicadores. Por lo dems, se pueden utilizar identicadores como
vrileEonEguiones, vrileConCmsEyEt IPQ, CE, vrileEinterrogtivccc, PQFFR, vrileGdividid, etc.Y, puesto que, el intrprete racket procesa archivos Unicode, los identicadores pueden contener y estar formados por cualesquiera caracteres vlidos en esa codicacin (se recomienda que los archivos de cdigo fuente estn en codicacin UTF-8). Por ejemplo, las siguientes declaraciones son vlidas para el intrprete de Racket:
b @define EenEespol IA b @define Edeutsh PA b @define e ho sn goE iu & udeEenEispernto QA
38
6.3 Llamadas a funciones
6.3. Llamadas a funcionesTpicamente una llamada a funcin tiene la forma
@`identifidorb `expresinbBAdonde la secuencia de expresiones determina el nmero de parmetros reales pasados a la funcin referenciada por el identicador. Por ejemplo
piA.
@prefijo holA
o
@horner
Racket dene muchas funciones integradas del lenguaje. Por ejemplo
stringElength, stringc, sqrt, C, E, `, ba, numerc, equlc,
stringEppend, sustring,
etc.
6.4. Bloques condicionales6.4.1. ifLa forma de un bloque condicional en Racket es:
@if `expresinElgib `expresinEprEverdderob `expresinEprEflsobACuando se evala un
if, se evala la primera expresin. Si esta resulta verdadera, se retorna
el resultado de la segunda expresin, y de lo contrario, el resultado de la tercera. Por ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> ( if ( < 1 2) " menor " " mayor ") " menor " > ( if ( positive ? ( sqrt 4) ) " s es positivo " " no es positivo ") " s es positivo " > ( define ( responder - saludo s ) ( if ( equal ? " hola " ( substring s 0 4) ) " hola , gusto de verte !" " perdn ?" ) ) > ( responder - saludo " hola programa ") " hola , gusto de verte !" > ( responder - saludo " El da est muy bonito , verdad ?") " perdn ?"Como en otros lenguajes de programacin, las sentencias condicionales (as como muchas otras cosas) se pueden anidar dentro de otras:
39
6 Elementos bsicos1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
> ( define ( responder - saludo s ) ( if ( string ? s ) ( if ( equal ? " hola " ( substring s 0 4) ) " hola , gusto de verte !" " perdn ?" ) " perdn , qu ?" ) ) > ( responder - saludo " hola programa ") " hola , gusto de verte !" > ( responder - saludo 3.1416) " perdn , qu ?" > ( responder - saludo " El da est muy bonito , verdad ?") " perdn ?"Esto tambin se podra escribir como:
1 2 3 4 5 6 7 8
> ( define ( responder - saludo s ) ( if ( if ( string ? s ) ( equal ? " hola " ( substring s 0 4) ) #f) " hola , gusto de verte !" " perdn , qu ?" ) )
6.4.2. and y orEn Racket, las funciones lgicas de conjuncin y disyuncin, son respectivamente y su sintaxis es:
@nd `expresinbBA 5f
y
@or `expresinbBA. 5f,
nd
y
or 5t
La primera retorna a
si encuentra que uno de sus parmetros se evala a
y retorna
en caso contrario. La segunda retorna
5t
y retorna
5f
5t
si encuentra que uno de sus parmetros se evala
en caso contrario. Funcionan como se espere que funcionen en otros
lenguajes de programacin, y adems funcionan en cortocircuito (como en otros lenguajes como
C
y
Java ).
Ejemplo:
1 2 3 4 5 6 7 8 9
> ( and ( < 3.1416 ( expt 10.1424 3.8) ) ( not ( negative ? pi ) ) ) #t > ( define ( responder - saludo s ) ( if ( and ( string ? s ) ( >= ( string - length s ) ( string - length " hola ") ) ( equal ? " hola " ( substring s 0 4) ) ) " hola , gusto de verte !"
40
6.4 Bloques condicionales
Figura 6.1: Grca de ecuacin seccionada
x < 1 x + 2 f (x) = 1 1 x < 0 2 x + 1 0 x
10 11 12
)
" perdn , qu ?" )
6.4.3. condUna forma de bloques condicionales anidadas (if anidados) es:
@ond { `expresinEdeEprueb `expresinbB }B AEste bloque condicional contiene una secuencia de clusulas entre corchetes. En cada clusula, la primera expresin es una expresin de prueba o evaluacin. Si esta se evala a verdadero, entonces las restantes clusulas del grupo son evaluadas, y la sentencia completa retorna el valor de la ltima expresin de esa clusula; el resto de las clusulas son ignoradas. Si la evaluacin de la expresin de prueba se evala a falso, entonces el resto de las expresiones de la clusula son ignoradas y la evaluacin contina con la prxima clusula. La ltima clusula puede usar la constante else que es un sinnimo para
5t.
41
6 Elementos bsicosPor ejemplo (ver la gura 6.1):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
> ( define ( seccionada x ) ( cond [( < x -1) (+ x 2) ] [( and ( >= x -1) ( < x 0) ) 1] [( >= x 0) (+ ( - ( sqr x ) ) 1) ]) ) > ( seccionada -4) -2 > ( seccionada -.5) 1 > ( seccionada 1) 0 >
;
x < -1: x +2
; -1 ( case (+ 7 5)
42
6.5 Bloques de cdigo secuencial2 3 4 5 6 7 8 9 10 11 12 13
[(1 2 3) " pequeo "] [(10 11 12) " grande "]) " grande " > ( case ( - 7 5) [(1 2 3) " pequeo "] [(10 11 12) " grande "]) " pequeo " > ( case (* 7 5) [(1 2 3) " pequeo "] [(10 11 12) " grande "] [ else " fuera de rango "]) " fuera de rango "
6.5. Bloques de cdigo secuencialEn la idea bsica del paradigma funcional, no existe algo como la est presente de manera nativa en los bloques y
secuencia de instrucciones,
pero como Racket es hbrido, s disponde esta caracterstica. La secuencia de instrucciones
let,
lmd, define (para funciones), ond, se
por lo que esas alternativas suelen bastar. Pero para aquellos casos en los que no, se
dispone del bloque
egin:
1 2 3 4 5 6 7 8 9 10
> ( if ( < 5 6) ( begin ( display " Aqu podemos escribir muchas cosas \ n ") " Pero slo el ltimo elemento ser el resultado " " cinco es menor que seis " ) " cinco no es menor que seis " ) Aqu podemos escribir muchas cosas " cinco es menor que seis "
6.6. Ms sobre llamadas a funcionesRacket es un lenguaje muy potente y muy expresivo. Las llamadas a funciones, no slo pueden hacerse utilizando directamente los identicadores de las funciones. Tambin pueden hacerse utilizando expresiones que devuelvan referencias a funciones. As, la sintaxis de llamadas a funciones se puede ampliar
1 como:
@`expresinEdeEfuninb `expresinbB ALa
`expresinEdeEfuninb,
debe ser una expresin cuyo resultado sea
una funcin.
Por ejemplo:
1
Esta an no es la forma ms general
43
6 Elementos bsicos1 2 3 4 5 6 7
> ( define ( duplicar valor ) (( if ( string ? valor ) string - append +) valor valor ) ) > ( duplicar " cadena ") " cadenacadena " > ( duplicar 3) 6Aqu, el bloque Si la
if
retorna una funcin a travs de su nombre (stringEppend o
C).
`expresinEdeEfuninb
no devolviera una funcin, se generara un error, ya que el
primer elemento dentro de los parntesis debe ser una funcin. Por ejemplo, la siguiente expresin:
b @I P QAproduce el error:
proedure pplitionX expeted proedureD givenX IY rguments wereX P QNote que, puesto que una funcin puede ser devuelta por una expresin, una funcin tambin puede se pasada como parmetro a otra funcin:
1 2 3 4 5 6
> ( define ( componer funcin valor ) ( funcin ( funcin valor ) ) ) > ( componer sqrt 256) 4 > ( componer sqr 2) 16
44
7 Funciones annimas - BloquesConsidere la siguiente expresin:
lambda
@C S RAEs equivalente a:
1 2 3 4
( define a 5) ( define b 4) ... (+ a b )La segunda forma sera innecesariamente larga si los valores de a y b slo se utilizarn una vez. De la misma manera, cuando una funcin slo se llama una vez, tener que declararla es innecesariamente largo. Por ello, Racket incluye la posibilidad de escribir funciones annimas. Por ejemplo:
1 2 3 4
> ( define ( poner - admiracin s ) ( string - append " " s "!") ) > ( componer poner - admiracin " hola ") " hola !!"Pero suponga que la funcin
ponerEdmirin slo llamar cuando se llame una vez a omponer. Entonces puede escribir la funcin ponerEdmirin directamente en la llamada a omponer desde donde ser invocada. Entonces se usan los bloques lmd.
7.1. Bloques lambdaEn Racket as como en muchos otros lenguajes de programacin, un produce una funcin directamente, sin tener que declararla. El bloque lambda tiene la siguiente sintaxis:
bloque lambda
@lmd @ `identifidorbB A `expresinbC ALa serie de identicadores se corresponde, uno a uno, con los parmetros formales de la funcin a producir; y las expresiones son el cuerpo de la funcin. Como en la declaracin
45
7 Funciones annimas - Bloques lambdatradicional de funciones (con
define)1 ,
el resultado de la funcin (cuando se llame), es el
resultado de la ltima expresin del cuerpo del bloque La evaluacin de un bloque
lmd.
lmd,
produce en s misma una funcin:
1 2
> ( lambda ( s ) ( string - append " " s "!") ) # < procedure >Entonces, usando
lmd,
la llamada a componer puede ser reescrita como:
1 2 3 4
> ( componer ( lambda ( s ) ( string - append " " s "!") ) " hola ") " hola !!" > ( componer ( lambda ( s ) ( string - append " " s "!?") ) " hola ") " hola !?!?"
7.2. Funciones/Expresiones que producen funcionesOtro uso de ciones:
lmd
es como resultado para una funcin (o expresiones) que produce fun-
1 2 3 4 5 6 7 8 9
> ( define ( hacer - Agregar - afijos prefijo sufijo ) ( lambda ( s ) ( string - append prefijo s sufijo ) ) ) > ( componer ( hacer - Agregar - afijos " ") " hola ") " < < hola > >" > ( componer ( hacer - Agregar - afijos " " "!") " hola ") " hola !!" > ( componer ( hacer - Agregar - afijos " < >") " hola ") " < < < < hola > > > >"Tambin pueden asignarse el resultado de una funcin que retorna funciones a un identicador:
1 2 3 4 5 6
> ( define poner - admiracin ( hacer - Agregar - afijos " " "!") ) > ( define menos - seguro ( hacer - Agregar - afijos " " "?!") ) > ( componer menos - seguro " ah nombre ") " ah nombre ?!?!" > ( componer poner - admiracin " en serio ") " en serio !!"Tambin puede asignarse directamente un bloque dos deniciones son equivalentes:
lmd a un identicador. Las siguientes
1 2 3 4
> ( define ( poner - admiracin s ) ( string - append " " s "!") ) > ( define poner - admiracin1
En realidad, lo tradicional, es usar lambda para denir funciones.
46
7.2 Funciones/Expresiones que producen funciones5 6 7 8 9
( lambda ( s ) ( string - append " " s "!") )) > poner - admiracin # < procedure : poner - admiracin >
47
7 Funciones annimas - Bloques lambda
48
8 Asignacin localHay al menos tres formas de hacer asignacin local en Racket: Con
letB.
define,
con
let
y con
8.1. defineHagamos otra ampliacin de la sintaxis para los bloques de funciones:
@define @`identifidorb `identifidorbB A `definiinbB `expresinbC Ay
@ lmd @ `identifidorbB A `definiinbB `expresinbC ALa diferencia con respecto a la sintaxis anteriormente mostrada, es que hay un bloque opcional de deniciones antes del cuerpo de la funcin. Por ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
> ( define ( conversar s ) ( define ( comienza - con ? prefijo ) ; local a conversar ( define longitud - prefijo ( string - length prefijo )) ; local a comienza - con ? ( and ( >= ( string - length s ) longitud - prefijo ) ( equal ? prefijo ( substring s 0 longitud - prefijo ) ) ) ) ( cond [( comienza - con ? " hola ") " hola , qu ondas ?"] [( comienza - con ? " adis ") " adis , nos vemos "] [ else " ah ?"]) ) > ( conversar " hola programa ") " hola , qu ondas ?" > ( conversar " hace fro en los talleres ") " ah ?" > ( conversar " adis programa ") " adis , nos vemos " > comienza - con ? reference to an identifier before its definition : comienza - con ?Todas las deniciones dentro de la denicin de una funcin, son locales a ella, y por tanto, invisibles desde fuera de ella. Como todo en Racket, las deniciones se pueden anidar indenidamente unas dentro de otras.
49
8 Asignacin local
8.2. letOtra forma de hacer asignaciones locales, es con el bloque bre
define
let.
Una ventaja de
let
so-
es que puede ser colocada en cualquier lugar dentro de una expresin y no
slo al principio de la funcin, como
define.
Adems, con
asignaciones al mismo tiempo, en lugar de hacer un La sintaxis de
define
let
se pueden hacer mltiples
para cada asignacin.
let es: @let @ { `identifidorb `expresinb }B A `expresinbC ACada clusula de asignacin es un cada clusula, al
`identifidorb let,
y una
`expresinb
rodeadas por
corchetes, y las expresiones que van despus de las clusulas, son el cuerpo del
`identifidorb
se le asigna el resultado de la
`expresinb
let.
En
para ser
usado dentro del cuerpo. Fuera del bloque Por ejemplo:
los identicadores no son visibles.
1 2 3 4 5 6 7 8 9 10 11
> ( let ([ x 1] [ y 2]) ( display ( string - append " La suma de " ( number - > string x ) " ms " ( number - > string y ) " es : " ( number - > string (+ x y ) ) ) ) ) La suma de 1 ms 2 es : 3 > (+ x y ) reference to an identifier before its definition : x
8.3. let*Las asignaciones de asignacin no se pueden referir unas a otras. El bloque clusulas posteriores, referencien clusulas anteriores:
let estn disponibles slo en el cuerpo del let, as que las clusulas de letB, por el contrario, permite que
1 2 3 4 5
> ( let * ([ x 1] [ y 2] [ z (+ x y ) ]) ( printf " La suma de ~ a y ~ a es : ~ a " x y z ) ) La suma de 1 y 2 es : 3
50
Parte III
Elementos del lenguaje
51
9 Listas e IteracinEn este captulo se describen los pares y sus casos particulares, las listas. Adems, se describen los mecanismos propios de Racket para procesar y recorrer listas.
9.1. ListasLas listas son el tipo de dato ms prominente de Racket, como dialecto de Scheme y a su vez de Lisp. No es de extraar que haya funciones especialmente avanzadas y de alto nivel para procesar y manipular listas. Hay varias maneras diferentes de crear listas en Racket. La principal de ellas es utilizando la funcin
list:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
> ( list " rojo " " verde " " azul ") (" rojo " " verde " " azul ") > ( list 1 2 3 4) (1 2 3 4) > ( list ( exp 1) ( sqrt 2) ) (2.718281828459045 1.4142135623730951) > ( list " cadena " 123 9.87654) (" cadena " 123 9.87654) > ( define mi - lista ( list " a " 2 3.1416) ) > mi - lista (" a " 2 3.1416)Otra forma, es utilizar la notacin tradicional de Lisp, con apstrofe:
1 2 3 4 5 6 7
> '(" otra lista " " con nmeros " 3 4 5.322) (" otra lista " " con nmeros " 3 4 5.322) > ( define mi - lista '(" otra lista " " con nmeros " 3 4 5.322) ) > mi - lista (" otra lista " " con nmeros " 3 4 5.322)
53
9 Listas e Iteracin
9.1.1. Lista vaca o nulaLa lista vaca, se puede escribir de diversas maneras en Racket: Invocando a la funcin
list
sin parmetros:
@listA
Con la constante especial Con la constante especial
empty null [email protected], que es un caracter de apstrofe seguido de
Con la forma tradicional de Lisp: parntesis vacos.
Para vericar si una expresin se evala a una lista vaca, se pueden utilizar tambin varias funciones: La funcin de evaluacin lgica La funcin Ejemplos:
emptyc: @if @emptyc vA v no vA
nullc: @if @nullc vA v no vA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
> '() () > empty () > null () > ( list ) () > (( lambda ( L ) ( if ( empty ? L ) " vaca " " no vaca ") ) null ) " vaca " > (( lambda ( L ) ( if ( empty ? L ) " vaca " " no vaca ") ) '() ) " vaca " > (( lambda ( L ) ( if ( null ? L ) " vaca " " no vaca ") ) empty ) " vaca " > (( lambda ( L ) ( if ( null ? L ) " vaca " " no vaca ") ) '(" a ") ) " no vaca "
9.1.2. Funciones bsicas sobre listaslengthpara vericar la longitud de una lista para extraer el i-simo elemento de una lista (los ndices comienzan desde
listEref
cero, como en la mayora de lenguajes de programacin).
54
9.1 Listasppendpara unir listas para invertir el orden de una lista
reverse memer listcvaca)
para vericar si un elemento est en una lista
para vericar si un identicador se corresponde con una lista (que puede estar
Ejemplos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
> '(" cero " 1 " dos " 3 " cuatro " 5.322) (" cero " 1 " dos " 3 " cuatro " 5.322) > ( length '(" cero " 1 " dos " 3 " cuatro " 5.322) ) 6 > ( list - ref '(" cero " 1 " dos " 3 " cuatro " 5.322) 2) " dos " > ( list - ref '(" cero " 1 " dos " 3 " cuatro " 5.322) 5) 5.322 > ( list - ref '(" cero " 1 " dos " 3 " cuatro " 5.322) 6) list - ref : index 6 too large for list : (" cero " 1 " dos " 3 " cuatro " 5.322) > ( append '(" cero " 1 " dos " 3 " cuatro " 5.322) ( list " a " " b " " c ") ( list " un elemento ") ) (" cero " 1 " dos " 3 " cuatro " 5.322 " a " " b " " c " " un elemento ") > ( reverse '(" cero " 1 " dos " 3 " cuatro " 5.322) ) (5.322 " cuatro " 3 " dos " 1 " cero ") > ( member " seis " '(" cero " 1 " dos " 3 " cuatro " 5.322) ) #f > ( if ( member " cero " '(" cero " 1 " dos " 3 " cuatro " 5.322) ) " s est " " no est ") " s est " > ( list ? empty ) #t > ( list ? 4) #f > ( list ? '(" hola ") ) #t
55
9 Listas e Iteracin
9.2. Iteracin automticaEn Racket no hay ciclos tos.
for o while1 , por lo que se utilizan ciertas funciones predenidas,
propias de los lenguajes funcionales, para recorrer y procesar secuencias (listas) de elemen-
9.2.1. mapLa primera de ellas, es la funcin
mp que utiliza los resultados de aplicar una funcin sobre
los elementos de una lista, para generar otra lista. Por ejemplo:
1 2 3 4 5 6 7 8 9
> ( map sqrt ( list 1 2 4 9 16) ) (1 1.4142135623730951 2 3 4) > ( map ( lambda ( x ) (+ 1 ( sqr x ) ) ) ( list -5 -4 -3 -2 -1 0 1 2 3 4 5) ) (26 17 10 5 2 1 2 5 10 17 26) > ( map ( lambda ( i ) ( string - append " " i "!") ) ( list " buenos das " " buenas noches ") ) (" buenos das !" " buenas noches !")
9.2.2. andmap y ormapOtras funciones tiles para hacer validaciones de listas son primera, retorna
ndmp
y
ormp.
En sus formas es
ms simples, ambas toman como parmetros una funcin y una lista. En el caso de la
5t;
y devuelve
5t si el resultado de evaluar la funcin sobre cada elemento de la lista 5f si el resultado de evaluar alguno de los elementos de la lista es 5f. ndmp. ormpdevuelve
La funcin
ormp
se comporta como se espera, pero aplicando disyuncin lgica en lugar
de conjuncin, que es lo que aplica
5t
si la funcin se evala a
verdadero para alguno de los elementos de la lista. Ejemplos:
1 2 3 4 5 6 7 8 9 10
> ( andmap string ? '(" una cadena " " otra cadena ") ) #t > ( andmap string ? '(" una cadena " " otra cadena " 123456) ) #f > ( andmap number ? ( list 1 3.35 1+8 i ) ) #t > ( andmap number ? ( list 1 3.35 1+8 i " el de la izquierda es un complejo ") )1
En realidad s hay, puesto que es un lenguaje funcional hbrido. Pero su necesidad es ciertamente algo que est fuera del paradigma funcional.
56
9.2 Iteracin automtica11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#f > ( ormap ( lambda ( x ) ( and ( real ? x ) ( positive ? x ) ) ) ( list " Slo complejos :" -1+1 i 0+8 i ( sqrt -4) -9 -5 i ) ) #f > ;;;;;;;; Ejemplo de validacin de parmetros con andmap : ;;;;;;;;;;;;; > ( define ( suma - tres - enteros - positivos a b c ) ( if ( andmap ( lambda ( x ) ( and ( integer ? x ) ( positive ? x ) ) ) ( list a b c ) ) (+ a b c ) " Los parmetros no son enteros positivos ") ) > ( suma - tres - enteros - positivos 2 3 5) 10 > ( suma - tres - enteros - positivos 2 3 -5) " Los parmetros no son enteros positivos "
9.2.3. filterLa funcin
filter
sirve para ltrar elementos de una lista, segn el criterio especicado
por una funcin de validacin. Ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
> ( filter string ? ( list 3 " a " " b" 4 5 6) ) (" a " " b ") > ( filter complex ? ( list " Slo complejos :" -1+1 i 0+8 i ( sqrt -4) -9 -5 i ) ) ( -1+1 i 0+8 i 0+2 i -9 -5 i ) > ; Dejar slo los elementos que sean impares y mltiplos de 3;;;;;;;;;;;;;;;;;;;; > ( filter ( lambda ( x ) ( and ( odd ? x ) ;; impar (= 0 ( remainder x 3) ) ) ) ;; residuo ( list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) ) (3 9 15) > ; Ahora como una funcin que recibe una lista como parmetro ;;;;;;;;;;;;;;;;;;;;; > ( define filtra - impares -y - mltiplos - de -3 ( lambda ( lista - nmeros ) ( if ( and ( list ? lista - nmeros ) ( andmap integer ? lista - nmeros ) ) ( filter ( lambda ( x ) ( and ( odd ? x ) (= 0 ( remainder x 3) ) ) )
57
9 Listas e Iteracin22 23 24 25 26 27 28 29 30 31 32 33
lista - nmeros ) " Esta funcin espera una lista de nmeros " ))) > ( filtra - impares -y - mltiplos - de -3 ( list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) ) (3 9 15) > ( filtra - impares -y - mltiplos - de -3 ( list " otra cosa ") ) " Esta funcin espera una lista de nmeros " > ( filtra - impares -y - mltiplos - de -3 " otra cosa ") " Esta funcin espera una lista de nmeros "
9.2.4. for-eachExiste la necesidad, eventualmente, de recorrer una lista, pero sin considerar el posible resultado de las evaluaciones. Generalmente, este sucede cuando necesitamos mostrar en pantalla cierta informacin, resultado de procesar una lista. Entonces, puede utilizarse la funcin nativa
forEeh:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
> ( for - each ( lambda ( x ) ( display x) ) ( list 1 2 3 4 5) ) 12345 > ( for - each ( lambda ( x ) ( display x) ( newline ) ) ( list 1 2 3 4 5) ) 1 2 3 4 5 > ;; Compare los resultados entre map y for - each : ;;;;;;;;;;;;;;;; > ( for - each integer ? ( list 2 3.1 4 5 6.6) ) > ( map integer ? ( list 2 3.1 4 5 6.6) ) (# t # f # t # t #f )
La funcin
forEeh,
a diferencia de
mp,
ignora el resultado de las evaluaciones de la
funcin sobre los elementos de la lista. Con
forEeh
slo importan los efectos colaterales
de las invocaciones (como las escrituras en pantalla o en archivo), no su resultado.
58
9.3 Iteracin manual
9.2.5. Versiones generales de las funciones de iteracinLas funciones
mp, forEeh, ndmp
y
ormp
pueden manipular mltiples listas, en lugar
de slo una. Las listas deben tener la misma longitud, y la funcin dada debe aceptar un parmetro por cada lista:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> ( map + ( list 1 2 3 4 5) ( list 10 100 1000 10000 100000) ) (11 102 1003 10004 100005) > ( map ( lambda ( s n ) ( substring s 0 n ) ) ( list " agua loca " " hoja de papel " " dulcera ") ( list 4 4 7) ) (" agua " " hoja " " dulcera ") > ;;;; Compare otra vez el comportamiento de map vs . for - each : ;;;;;;;;;;;;;; > ( map / ( list 1 2 3 4 5) ( list 5 4 3 2 1) ) (1/5 1/2 1 2 5) > ( for - each ( lambda ( a b ) ( printf "~ a \ n " (/ a b ) ) ) ( list 1 2 3 4 5) ( list 5 4 3 2 1) ) 1/5 1/2 1 2 5
9.3. Iteracin manualEventualmente es necesario procesar listas a ms bajo nivel que el que proveen funciones como
mp.
En esos casos, se requiere de mecanismos
ms primitivos
como los siguientes:
first
devuelve el primer elemento de una lista no vaca
rest devuelve una lista con los elementos de una lista no vaca, sin su primer elemento(el resultado puede ser una lista vaca si la lista de entrada tena slo un elemento)
onsEjemplos:
concatena un elemento a una lista, produciendo una lista nueva
onsc verica si un elemento es una lista no vaca (lo contrario de emptyc y de nullc)1 2 3 4 5 6
> ( first ( list 1 2 3) ) 1 > ( rest ( list 1 2 3) ) (2 3)
59
9 Listas e Iteracin7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
> ( cons " cabeza " empty ) (" cabeza ") > ( cons " nueva " ( cons " cabeza " empty ) ) (" nueva " " cabeza ") > ( empty ? empty ) #t > ( empty ? ( cons " cabeza " empty ) ) #f > ( cons ? empty ) #f > ( cons ? ( cons " cabeza " empty ) ) #t
9.3.1. AplicacinTeniendo a nuestra disposicin estas funciones de
bajo nivel
para manipular funciones,
podramos construir nuestras propias funciones de longitud de lista y de mapeo de lista:
1 2 3 4 5 6 7 8 9 10
( define ( longitud L ) ( cond [( empty ? L ) 0] [ else (+ 1 ( longitud ( rest L ) ) ) ]) ) ( define ( mapear f L ) ( cond [( empty ? L ) empty ] [ else ( cons ( f ( first L) ) ( mapear f ( rest L ) ) ) ]) )Tambin podemos hacer funciones que procesen listas de manera bsica. Por ejemplo considere la siguiente funcin para generar listas de nmeros enteros:
1 2 3 4 5 6 7 8 9 10 11 12 13
( define secuencia - de - enteros ( lambda ( num - elementos inicio paso ) ( define ( aux i contador lista ) ( if ( >= contador num - elementos ) ( reverse lista ) ( aux (+ i paso ) ( add1 contador ) ( cons i lista ) ) )) ( if ( and ( exact - nonnegative - integer ? num - elementos ) ( integer ? inicio ) ( integer ? paso ) ) ( aux inicio 0 empty ) ( error " Error en los parmetros ") )
60
9.4 Pares y listas14
))
9.4. Pares y listasLa funcin
ons acepta dos parmetros, y el segundo no necesariamente debe ser una lista.Paro
En el caso que como segundo argumento se le pase algo que no sea una lista, la funcin cons devuelve un
Pareja.
Un Par
en Racket no es otra cosa que dos elementos (de cualquier tipo), ligados entre s.
Una lista no vaca, de hecho, es un par compuesto por un elemento (el primero) y una lista (que puede ser vaca). La notacin que utiliza Racket para representar los pares es la de los elementos, encerrados entre parntesis y separados por un espacio en blanco, un punto y otro espacio en blanco:
1 2 3 4 5
> ( cons 1 2) (1 . 2) > ( cons " una cadena " 4) (" una cadena " . 4)Hay una funcin equivalente a funciones correspondientes a
onsc con ms sentido para los pares: pirc. Tambin hay first y rest para pares: r y dr. Estas ltimas funcionan
con cualquier tipo par (incluyendo las listas no vacas) y las primeras, slo funcionan con listas no vacas, pero no con pares. Ejemplos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> ( define vaco '() ) > ( define par ( cons 1 2) ) > ( define lista ( cons 1 ( cons 2 '() ) ) ) > ( pair ? vaco ) #f > ( pair ? par ) #t > ( pair ? lista ) #t > ( car par ) 1 > ( car lista ) 1 > ( cdr par ) 2 > ( cdr lista ) (2) > ( list ? vaco ) #t
61
9 Listas e Iteracin21 22 23 24
> ( list ? par ) #f > ( list ? lista ) #t
9.4.1. Convencin de impresinRacket tiene una convencin para imprimir los pares, que puede llegar a ser muy confusa. Por ejemplo, considere el siguiente resultado:
1 2
> ( cons 0 ( cons 1 2) ) (0 1 . 2)Lo anterior es un par, cuyo segundo elemento es otro par que no es una lista. La regla para la impresin es la siguiente: Usar siempre la notacin de punto, pero si el punto est inmediatamente seguido de una apertura de parntesis, entonces, remover el punto, el parntesis de apertura y el correspondiente parntesis de cierre.
@H F @I F PAA se convierte en @H I F PA. La utilidad de esta, aparentemente, extraa regla, es para volver legibles las listas, ya que, por ejemplo, @I F @P F @Q F @AAAA que es una lista de tres elementos en su notacin de punto se convierte en @I P QA, lo cual esAs, ms fcil de leer.
9.4.2. Notacin injaExiste una convencin particular en Racket que, aunque no es tradicional en Lisp y otros dialectos de Scheme, puede mejorar la legibilidad de ciertas partes de nuestras funciones. Un par de
puntos
pueden aparecer alrededor de un solo elemento en una se-
cuencia parentizada, mientras el elemento no sea ni el primero ni el ltimo. Esta convencin de sintaxis ejecuta una conversin que mueve el elemento entre los
puntos
hacia el frente de la secuencia parentizada.
Esta convencin posibilita una especie de notacin inja, a la cual estamos ms acostumbrados:
1 2 3 4 5 6 7 8
> (1 . + . 2 3 4 5) 15 > '(1 . + . 2 3 4 5) (+ 1 2 3 4 5) > (1 . < . 2) #t
62
9.4 Pares y listas9 10 11 12 13 14 15 16 17
> '(1 . < . 2) ( < 1 2) > (1 2 3 . * . 4) 24 > '(1 2 3 . * . 4) (* 1 2 3 4)
63
9 Listas e Iteracin
64
Ejercicios de Listas e iteracin1. Dada una lista desordenada de nmeros enteros ordenar dicha lista de mayor numero a menor, tomar en cuenta que pueden existir nmeros repetidos en dicha lista (No utilizar la funcin
sort).
2. Dada una lista compuesta por nmeros enteros eliminar los elementos repetidos de dicha lista. Retornar una nueva lista. Nota: Se pide se pide usar
disply,
retornar
un lista, es decir que no
por lo dems, se puede utilizar cualquier primitiva.
3. Dada una lista compuesta por cadenas, construir una nueva lista a partir de la anterior formada por los elementos que no estn repetidos. Ejemplo para mayor comprensin:
[email protected] mundo mundoA
la nueva lista ser
4. Dada una lista compuesta por cadenas, construir una cadena formada por cada cadena
[email protected] mundoA retornar holmundo. (Note que de ser la segunda cadena mundo se retornara hol mundo. Puede usar las primitivas que desee. Se recomienda leer sobre stringEppend.que se encuentre en la lista. Ejemplo 5. Dada una lista compuesta por listas, retornar verdadero si todas las sublistas estn vacas y falso si por lo menos una posee algn elemento. Puede usar cualquier primitiva. 6. Dada una lista compuesta por 5 nmeros no repetidos, retornar el nmero mayor de dicha lista (ojo se pide retornar no usar
disply).
7. Dada una lista compuesta por 5 cadenas no repetidas, retornar la cadena de mayor longitud. En caso de que existan 2 o ms cadenas de igual longitud y estas resulten las de mayor longitud, retornar ambas cadenas (para facilitar el ejercicio puede retornar la cadena o las cadenas dentro de una lista). 8. Dada una lista compuesta por nmeros enteros, desplegar la cantidad de nmeros pares y la cantidad de nmeros impares. 9. Dada una lista compuesta por nmeros enteros, retornar la sumatoria de todos los nmeros pares. 10. Dada una lista compuesta por nmeros enteros y dado un nmero, retornar nmero se encuentra en la lista y
memer).
5f
5t
si el
si dicho nmero no se encuentra (NO USAR
11. Dada una lista compuesta por nmeros y dado un nmero, eliminar dicho nmero de la lista si este se encuentra en ella (puede usar cualquier primitiva).
65
9 Listas e Iteracin12. Dada una lista compuesta por tres puntos (un punto es una lista, ejemplo un punto y
x 1, y 2)
retornar
5f
5t
es
si dichos puntos forman un tringulo equiltero,
en caso contrario (es equiltero si sus tres lados son iguales). NOTA : Frmula
de distancia entre los puntos
(x1 , y1 )
y
(x2 , y2 ): d =
(x2 x1 )2 + (y2 y1 )2
13. Dada una lista compuesta por listas, retornar una lista compuesta por los elementos de cada sublista. Ejemplo
[email protected] @I PA @P QAA retornar @I P P QA. Como puede observar,
pueden existir elementos repetidos. 14. Dada una lista compuesta por cadenas, retornar la cantidad de vocales dentro de dicha lista. Ejemplo
[email protected] mundoA
retornar 4.
15. Dada una lista compuesta por cadenas, retornar la lista compuesta por las cadenas sin sus vocales. Ejemplo:
[email protected] mundoA
retornar
[email protected] mndA
note que se
eliminaron las vocales. El orden de las cadenas no debe cambiar. 16. Dada una cadena, pasar cada letra de la cadena a una lista, ejemplo vierte en forma de cadena. 17. Dada una lista compuesta por cadenas, ordenar dicha lista tomando como criterio la longitud de las cadenas (No usar
[email protected] o l A. Note que no se piden los caracteres si no las letras en
hol
se con-
sort).
18. Elaborar una funcin que reciba como parmetro una lista de nmeros enteros y positivos, la funcin evaluar la lista de nmeros, si la lista est ordenada de mayor a menor, la funcin retornar dos listas (usando la funcin
vlues)
la primer lista
contendr los nmeros pares de la lista original, respetando el mismo orden de mayor a menor, y la segunda lista contendr los nmeros impares de la lista original respetando el orden de la lista original; en caso contrario, es decir si la lista pasada de parmetro est desordenada, se retornar la lista ordenada de mayor a menor.
66
10 Recursin10.1. Recursin por Posposicin de trabajoEn el caso del siguiente cdigo de la funcin
longitud,
el tipo de recursin usada es
posposicin de trabajo:1 2 3 4
( define ( longitud L ) ( cond [( empty ? L ) 0] [ else (+ 1 ( longitud ( rest L ) ) ) ]) )Y al evaluar, por ejemplo,
@longitud @list AA
se da este proceso:
1 2 3 4 5 6 7 8
-> = = = = = = =
( longitud ( list " a " " b " " c ") ) (+ 1 ( longitud ( list " b " " c ") ) ) (+ 1 (+ 1 ( longitud ( list " c ") ) ) ) (+ 1 (+ 1 (+ 1 ( longitud ( list ) ) ) ) ) (+ 1 (+ 1 (+ 1 0) ) ) (+ 1 (+ 1 1) ) (+ 1 2) 3
Como puede verse, se tienen que apilar todos los clculos y todas las sumas quedan
tas
pospues-
hasta que se alcanza el caso trivial de la recursin, que en este caso es cuando se en-
cuentra una lista vaca. Si la longitud de la lista es demasiado grande, provocar un gran consumo de memoria. Esto no es algo extrao , sin embargo resulta ser ineciente en Racket, ya que este lenguaje provee una optimizacin importante para la recursin de cola, que se explica a continuacin.
10.2. Recursin de ColaConsidere la siguiente versin de
longitud
con recursin de cola:
1 2 3 4 5
( define ( longitud L ) ; funcin local longitud - aux : ( define ( longitud - aux L longitud - actual ) ( cond [( empty ? L ) longitud - actual ]
67
10 Recursin6 7 8
[ else ( longitud - aux ( rest L ) (+ longitud - actual 1) ) ]) ) ; este es el cuerpo de longitud , que llama a longitud - aux : ( longitud - aux L 0) )Ahora veamos el clculo de
@longitud @list AA:" b " " c ") ) " a " " b " " c ") 0) " b " " c ") 1) " c ") 2) ) 3)
1 2 3 4 5 6
-> = = = = =
( longitud ( list " a " ( longitud - aux ( list ( longitud - aux ( list ( longitud - aux ( list ( longitud - aux ( list 3
Note que no hay retornos pendientes en ningn momento, tampoco hay clculos (en este caso, sumas) que queden pendientes en cada paso de la recursin. En Racket, cuando una funcin se reduce a una expresin cuyos parmetros son totalmente conocidos, toda la memoria de la funcin es liberada y ya no queda rastro de su invocacin. Esto no slo sucede con la recursin de cola, sino con cualquier llamada para la cual no queden clculos pendientes. Esta es una diferencia importante de Racket con respecto a otros lenguajes de programacin no funcionales, ya que en otros lenguajes, an haciendo recursin de cola, siempre queda memoria de las llamadas anteriores, apiladas esperando algn
return, end
o equivalente.
Esto provoca que la cantidad de memoria necesaria para ejecutar el procedimiento recursivo es aproximadamente lineal a la profundidad de la llamada. En Racket, la recursin de cola se ejecuta en una cantidad de memoria ja, para toda la ejecucin de la funcin recursiva. Queda entonces, la atenta invitacin a utilizar recursin de cola en los programas hechos con Racket, siempre que sea posible.
68
11 Tipos de dato integrados del lenguajeAqu se describen los principales tipos integrados, nativos de Racket. El lenguaje incluye muchos otros tipos de datos complejos que no sern abordados aqu.
11.1. BooleanosEl tipo ms simple de Racket es el que son
5t para verdadero y 5f para falso (tambin se aceptan las formas 5p y 5, pero las oolencque verica si un valor es una de las dos constantes lgicas,
booleano
o
lgico.
Slo tiene dos valores constantes,
versiones en minsculas son preferidas). Existe la funcin o
5f:
5t
1 2 3 4
> ( boolean ? 0) #f > ( boolean ? # f ) #tA pesar de que se espera un valor de verdad en las expresiones de prueba de las construcciones
if, ond, nd, or y otras, todos los valores posibles en Racket, excepto 5f se evalan
como verdadero:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
> ( define ( mostrar - valor - de - verdad v ) ( if v # t # f )) > ( mostrar - valor - de - verdad "") #t > ( mostrar - valor - de - verdad " no ") #t > ( mostrar - valor - de - verdad empty ) #t > ( mostrar - valor - de - verdad '(1 2 3) ) #t > ( mostrar - valor - de - verdad #() ) #t > ( mostrar - valor - de - verdad #(1 2 3) )
69
11 Tipos de dato integrados del lenguaje19 20 21 22
#t > ( mostrar - valor - de - verdad #\ a ) #t
11.2. NmerosA continuacin se presenta el tratamiento de los
nmeros
en Racket.
Un valor numrico se puede validar con la funcin
numerc:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
> ( number ? 3) #t > ( number ? 3.1416) #t > ( number ? "3") #f > ( number ? 5+8 i ) #t > ( number ? 5/8) #t > ( number ? 3.45 e -200) #t
11.2.1. ClasicacinHay dos formas de clasicar nmeros en Racket: Por exactitud y por conjuntos.
Clasicacin por ExactitudEn Racket, un Los
nmero
es
exacto
o
inexacto.
nmeros exactos
son:
1. Los enteros 2. Los racionales 3. Los complejos con parte real exacta y parte imaginaria exacta Los
nmeros inexactos
son:
70
11.2 Nmeros1. Los reales de coma otante 2. Los complejos con parte real inexacta o parte imaginaria inexacta Existen las funciones
extc e inextc para determinar si un nmero pertenece a uno de
los dos tipos anteriores.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
> ( exact ? 7) #t > ( inexact ? 7) #f > ( inexact ? empty ) . . inexact ?: expects argument of type < number >; given () > ( inexact ? "") . . inexact ?: expects argument of type < number >; given "" > ( inexact ? 8.999993 -8.325421 i ) #t > ( inexact ? 7/8) #fPueden tambin utilizarse las funciones de un tipo a otro:
extEbinext e inextEbext para convertir
1 2 3 4 5 6 7 8
> ( exact - > inexact 1/3) 0.3333333333333333 > ( exact - > inexact (/ 7 8) ) 0.875 > ( inexact - > exact 0.3333333333333333333333333333) 6004799503160661/18014398509481984Adems, existe una forma de forzar la representacin, como exacto o inexacto, de un nmero, independientemente de la forma en que se escriba. Con los prejos
5e
y
5i:
1 2 3 4 5 6 7 8
> # e0 .2 1/5 > # i1 /5 0.2 > # i4 +5 i 4.0+5.0 i
Propagacin de la exactitudlos clculos:
Con los operadores aritmticos bsicos, los nmeros exactos
se mantienen exactos tras los clculos y los inexactos se mantienen inexactos a travs de
71
11 Tipos de dato integrados del lenguaje1 2 3 4 5 6 7 8 9 10
> ( define ( sigma f a b ) ( if (= a b ) 0 (+ ( f a ) ( sigma f (+ a 1) b )) ) ) > ( sigma ( lambda ( x ) (/ 1 107/210 x ) ) 5 8)
> ( sigma ( lambda ( x ) (/ 1.0 x ) ) 5 8) 0.5095238095238095
Clasicacin por ConjuntosTal como en la matemtica tradicional, los nmeros se categorizan por la jerarqua del conjunto al que pertenecen:
ZQRC
(es decir, los enteros estn includos en los
racionales, estos en los reales, y estos en los complejos):
1 2 3 4 5 6 7 8 9 10 11
> ( integer ? -5) #t > ( rational ? -5/9) #t > ( real ? -5/9) #t > ( complex ? -5/9) #t
11.2.2. Otras basesLa base para todos los nmeros (desde los enteros hasta los complejos) es forzarse a que sea base 2, base 8 o base 16 con los prejos
5, 5o, 5x,
10,
pero puede
respectivamente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
> # b11 3 > # o10 8 > # xff 255 > # b111 .01 7.25 > # xf /5 3
72
11.2 Nmeros
11.2.3. ComparacionesLos nmeros exactos pueden ser comparados con la funcin de
a o con equlc, pero los nmeros
inexactos, debido a su propia naturaleza, deberan ser comparados
por igualdad, ya que su representacin no es exacta:
por proximidad
en lugar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
> (= 3 6/2) #t > (= 4+8 i 8/2+24/3 i ) #t > ( equal ? 4+8 i 8/2+24/3 i ) #t > (= 4.0+8.0 i 8/2+24/3 i ) #t > (= 4.0 4) #t > (= 0.1 1/10) #f > ( inexact - > exact 0.1) 3602879701896397/36028797018963968 > ( let ([ a 0.1] [ b 1/10] [ tolerancia 0.00001]) ( < ( abs ( - a b ) ) tolerancia ) ) #t > ( define ( son - reales - iguales ? a b tol ) ( < ( abs ( - a b ) ) tol ) )
11.2.4. Constantes especialesExisten cuatro constantes especiales, denidas por la IEEE:
CinfFH/EinfFH
que resultan de sobrepasar la capacidad de representacin de los
nmeros en coma otante, por arriba o por abajo, respectivamente.
CnnFH/EnnFH que resultan de clculos indeterminados como cero entre cero, innitoentre innito, cero por innito, innito menos innito, etc.
1 2 3 4
> (/ 8.0 0.0) + inf .0 > -5.38 e700
73
11 Tipos de dato integrados del lenguaje5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
- inf .0 > 1.79 e -400 0.0 > 1.79 e308 1.79 e +308 > 1.79 e309 + inf .0 > ;; 'NaN ' significa : Not a Number . > (/ 0.0 0.0) + nan .0 > (/ + inf .0 - inf .0) + nan .0 > (* 0.0 - inf .0) + nan .0 > (+ + inf .0 - inf .0) + nan .0Si estos valores especiales se pasan como parmetro a alguna funcin que espere nmeros, su resultado ser del mismo tipo (excepto para algunas funciones para las que tiene signicado):
1 2 3 4 5 6 7 8
> ( cos (* (+ (* 0.0 - inf .0) 1) 9) ) + nan .0 > ( atan + inf .0) 1.5707963267948966 > (* 2 ( atan + inf .0) ) ; pi 3.141592653589793
11.3. CaracteresUn
caracter
en Racket, es un valor escalar Unicode (igual que en otros lenguajes de pro-
gramacin como
Java ).
Los caracteres literales, se expresan como una secuencia
5
seguido del caracter correspon-
diente, si es que estos tienen una representacin imprimible y escribible:
1 2 3 4
> #\0 #\0 > #\ a #\ a
74
11.3 Caracteres5 6 7 8 9 10
> #\ newline #\ newline > #\ space #\ space > #\& #\&
A pesar que un caracter se corresponda con un entero en Racket, a diferencia de otros lenguajes (como
Java
o
C ),
no se pueden mezclar directamente con los nmeros. Para
poder hacerlo, se utilizan las funciones
hrEbinteger
e
integerEbhr:
Si algn caracter no tiene una representacin imprimible, este siempre se puede mostrar con la notacin Unicode tradicional de una letra dos bytes:
u
minscula y un nmero hexadecimal de
1 2 3 4
> ( integer - > char 17) #\ u0011 > ( char - > integer #\ u011D ) 285
Existen ciertas funciones tiles para manipular y procesar caracteres:
75
11 Tipos de dato integrados del lenguaje
11.4. CadenasUna
cadena
es un arreglo de caracteres de longitud ja. Como en muchos otros lenguajes,
se escriben entre comillas dobles. Como en otros lenguajes, para poder escribir comillas dobles dentro de la cadena, hay que
. Esto se conoce como secuencia de escape. De la misma manera, hay varias secuencias de escape, como para escribir una pleca, n para una nueva lnea, r para un retorno de carro. Y para escribir un caracter dado su cdigo octal, UUU y upppputilizar la secuencia para escribirlo en funcin de su cdigo hexadecimal Unicode. La funcin
disply
escribe los caracteres de la cadena, pero sin las comillas, a diferencia
de lo que sucede cuando el resultado de una expresin es una cadena.
76
11.4 CadenasEjemplos:
Hay tres funciones bsicas para la creacin y manipulacin de cadenas:
string
forma una nueva cadena a partir de una serie de caracteres; devuelve un caracter de una cadena, dada su posicin; y devuelve su longitud medida en caracteres
stringErefEjemplos:
stringElength1 2 3 4 5 6 7 8 9 10 11 12 13
> ( string #\ H #\ o #\ l #\ a ) " Hola " > ( string ) "" > ( string - ref " Hola " 0) #\ H > ( string - ref " Hola " 3) #\ a > ( string - length " Hola ") 4
11.4.1. Cadenas mutablesPor defecto, los literales de cadena escritos en el cdigo fuente, se convierten en cadenas
inmutables,crear una
es decir, que no pueden ser cambiados durante el curso de su existencia como Veamos las funciones para crear una cadena mutable y alterar
objetos del programa. Pero si requerimos alterar una cadena durante la ejecucin, debemos
cadena mutable.
su contenido:
mkeEstring
recibe una longitud para la nueva cadena mutable y opcionalmente un
caracter de relleno, por defecto el caracter nulo (uHHHH).
77
11 Tipos de dato integrados del lenguajestringEset3modica un caracter de una cadena mutable, dada su posicin. convierte una cadena mutable en su versin inmutable
stringEbimmutleEstring
(si recibe una inmutable, la devuelve a ella misma).
immutlec verica si un objeto es inmutable no slo las cadenas pueden ser mutables.
stringEopy31 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
copia total o parcialmente el contenido de una cadena mutable o
inmutable a otra cadena mutable.
> ( make - string 4 #\ c ) " cccc " > ( define cadena - mutable ( make - string 4 #\ c ) ) > ( string - length cadena - mutable ) 4 > ( string - ref cadena - mutable 2) #\ c > ( string - set ! cadena - mutable 2 #\ a ) > cadena - mutable " ccac " > ( define cadena - inmutable ( string - > immutable - string cadena - mutable ) ) > ( immutable ? cadena - inmutable ) #t > ( immutable ? cadena - mutable ) #f > ( define otra - cadena - mutable ( make - string 10) ) > otra - cadena - mutable "\ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 " > ( string - copy ! otra - cadena - mutable 0 " buen da ") > otra - cadena - mutable " buen da \ u0000 \ u0000 "
11.4.2. Comparacin entre cadenasLa comparacin entre cadenas se realiza con las siguientes funciones:
stringac, string`c, string`ac, stringbc, stringbac
para hacer comparaciones
simples en funcin del orden relativo de los caracteres en el estndar Unicode.
78
11.4 CadenasstringEiac, stringEi`c, stringEi`ac, stringEibc, stringEibacpara hacer
comparaciones insensibles al caso (sin distincin entre maysculas o minsculas).
stringEloleac, stringElole`c, stringElolebc, stringEloleEiac, stringEloleEi`c, stringEloleEibc para hacer comparaciones en funcin de ciertas consideracionesalfabticas y lexicogrcas, en lugar de slo por las posiciones en Unicode. Ejemplos:
1 2 3 4 5 6 7 8 9 10 11
> ( string - ci
Recommended