Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Racket
Racket
Universidad Centroamericana
Jos Simen Caas
Eduardo NAVAS
versin 1.0
2010.07.21
Este libro fue desarrollado nicamente con software libre. Entre las herramientas usadas,
CC-BY-NC-SA
Este es un libro libre con la licencia
de la
Prlogo
Este 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
ndice general
I. Introduccin a la Programacin Funcional con Racket
17
1. Programacin Funcional
19
1.1.
Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
1.2.
Caractersticas
20
1.3.
. . . . . . . . . . . . . . . . . . . .
20
1.4.
21
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2. Instalacin de Racket
23
2.1.
2.2.
. . . . . . . . . . . . . . . . . . . . . . .
23
. . . . . . . . . . . . . . . . . . . . . . . . . .
24
2.2.1.
Debian . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
2.2.2.
Fedora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
27
3.1.
27
3.2.
27
4.2.
29
Ejecucin interactiva . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
4.1.1.
4.1.2.
Ejecucin no interactiva
4.2.1.
. . . . . . . . . . . . . . .
30
. . . . . . . . . . . . . . . . . . . .
30
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
31
. . . . . . . . . . . . . . . . . .
31
33
5.1.
33
5.2.
33
35
6. Elementos bsicos
37
6.1.
Comentarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
ndice general
6.2.
Deniciones Globales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
37
6.2.1.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
6.3.
Llamadas a funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
6.4.
Bloques condicionales
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
41
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
42
6.4.1.
6.4.2.
6.4.3.
6.4.4.
Identicadores
if . . .
and y or
cond . .
case . .
6.5.
43
6.6.
43
45
7.1.
Bloques
7.2.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
8. Asignacin local
8.1.
8.2.
8.3.
define
let . .
let* .
45
46
49
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
49
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
51
9. Listas e Iteracin
53
9.1.
9.2.
Listas
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
53
9.1.1.
54
9.1.2.
. . . . . . . . . . . . . . . . . . . . . .
54
Iteracin automtica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
9.2.4.
map . . . . . . .
andmap y ormap
filter . . . . .
for-each . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
58
9.2.5.
59
9.2.1.
9.2.2.
9.2.3.
9.3.
Iteracin manual
9.3.1.
9.4.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
Aplicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
61
9.4.1.
Pares y listas
Convencin de impresin . . . . . . . . . . . . . . . . . . . . . . . . .
62
9.4.2.
Notacin inja
62
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.Recursin
10
67
67
67
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
ndice general
69
11.1. Booleanos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
11.2. Nmeros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
11.2.1. Clasicacin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
. . . . . . . . . . . . . . . . . . . . . . .
70
. . . . . . . . . . . . . . . . . . . . . . .
72
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
72
11.2.3. Comparaciones
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
73
11.3. Caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
11.4. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
77
. . . . . . . . . . . . . . . . . . . . . . .
78
79
80
11.6. Smbolos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
83
83
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11.9. Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
84
11.10.Tablas Hash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
85
11.11.Void
86
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
12.1. La funcin
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
12.2. Bloques
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
89
. . . . . . . . . . . .
90
. . . . . . . . . . .
90
91
. . . . . . . . . . . . . . . . .
92
93
arity-at-least . . . . . . .
procedure-arity . . . . . . .
procedure-arity-includes?
94
. . . . . . . . . . . . . . . . . . . . . .
94
. . . . . . . . . . . . . . . . . . . . . .
95
values . . . . . . . . . . . .
define-values . . . . . . .
let-values, y let*-values
12.4. Asignaciones
94
. . . . . . . . . . . . . . . . . . . . . .
96
. . . . . . . . . . . . . . . . . . . . . . .
97
. . . . . . . . . . . . . . . . . . . . . . .
97
. . . . . . . . . . . . . . . . . . . . . . .
97
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
98
101
101
11
ndice general
13.2. Estructuras derivadas
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
102
104
104
14.Mdulos Funcionales
109
. . . . . . . . . . . . . . . . . . . .
15.Entrada y Salida
15.1. Imprimir datos
111
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
111
113
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
113
114
115
15.3.1. Archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
open-input-file . . . . .
open-output-file . . . .
open-input-output-file
116
. . . . . . . . . . . . . . . . . . . . . . . .
116
. . . . . . . . . . . . . . . . . . . . . . . .
116
. . . . . . . . . . . . . . . . . . . . . . . .
117
Ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
117
Procesamiento automatizado
118
. . . . . . . . . . . . . . . . . . . . . .
15.3.2. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
119
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
120
122
16.Excepciones
127
127
128
eval
131
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . .
12
110
131
132
133
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
133
133
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
133
18.4. Mtodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
134
134
. . . . . . . . . . . . . . . . . . . . . . . . .
134
. . . . . . . . . . . . . . . . . . . . . . . . .
135
135
136
18.7. Ejemplos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
137
ndice general
141
143
143
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
144
144
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
147
148
19.6. Pneles
150
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
153
163
21.1. Dibujo en un
canvas %
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
163
canvas %
. . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . .
174
177
22.Mens
165
171
23.Proyecto: Minipaint
183
V. Apndices
197
199
13
ndice general
14
ndice de guras
2.1.
6.1.
. . . . . . . . . . . . . . . . . . . . . . . . . . .
x < 1
x + 2
f (x) = 1
1 x < 0
2
x + 1 0 x
24
. . . . . . .
41
19.1. hola-mundo.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
143
19.2. eventos-1.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
144
19.3. eventos-2.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
145
19.4. eventos-3.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
146
19.5. dialogo.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
147
19.6. text-eld.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
148
19.7. pneles.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
150
153
153
154
155
156
157
158
21.1. canvas1.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
163
21.2. canvas2.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
165
21.3. canvas3.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
167
21.4. canvas4.rkt
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
169
. . . . . . . . . . . . . . . . . .
171
. . . . . . . . . . . . . . . . .
172
22.3. 1-mens.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
173
22.4. 2-mens.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
175
. . . . . . . . . . . . . . . . . . . . . . . . . . .
179
180
181
. . . . . . . . . . . . . . . . . . . .
15
ndice de guras
23.1. mini-paint.rkt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
183
Parte I
Introduccin a la Programacin
Funcional con Racket
17
1 Programacin Funcional
La 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. Objetivo
El 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
Java ).
1
2
3
4
5
6
7
8
9
10
11
12
13
C:
// 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 ) ;
}
14
19
1 Programacin Funcional
15
16
17
18
19
20
21
22
programa.
1.2. Caractersticas
Los 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
ros 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
no-funcional.c,
10,
aumentar_contador(10)
for, ni while, etc.). Esto obliga en la prctica, a que todas las repeticiones de instrucciones
se lleven a cabo por medio de funciones recursivas.
20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1
2
1
2
3
4
1
2
21
1 Programacin Funcional
En 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 ,
22
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]
2 Instalacin de Racket
2.1. Instalacin con el instalador ocial
A 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
/usr/plt,
para la cual
/usr/share/doc/plt,
/usr/plt/doc/.
/usr/share/plt,
index.html.
$ raco docs
se lanza la pgina del ndice de la documentacin instalada con el navegador por defecto
del Sistema Operativo.
o simplemente ejecutar:
$ sh racket-xxxx.sh
23
2 Instalacin de Racket
Por el momento , las distribuciones de GNU/Linux no incluyen la nueva versin (la 5.0) de
Racket.
PLT Scheme
(que es completamente
compatible con todo el contenido de este libro , en esta primera versin). Es slo cuestin
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
llamada
PLT Scheme
en sus repositorios.
2.2.1. Debian
En distribuciones basadas en
ocial de la versin instalada por el paquete anterior. Con este paquete, est disponible la
pgina
2
3
/usr/share/plt/doc/index.html
24
2.2.2. Fedora
En distribuciones
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
<smbolo_no_terminal>.
<
>
representan smbolos no
define, (, ), let.
}.
El metasmbolo
+,
El metasmbolo
*,
(<operador> <operando>*),
es decir,
(*
(>
(+
(+
2
5
2
4
3) -> equivale a (2 * 3)
6)-> equivale a (5 > 6)
3 10)-> equivale a (2 + 3 + 10)
(* 3 2))-> equivale a (4 + 3 * 2)
5a + 2bc2
es:
(+ (* 5 a) (* 2 b c c)).
27
28
racket,
racket
cin y compilacin).
En el caso de
que este Entorno se acomoda a diversas variantes de Scheme soportadas por el intrprete
racket.
y compilador
#lang racket
Esta 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.
racket),
el lenguaje
racket,
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.
29
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
substring,
substring.
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
racket,
1
2
3
enter!
acin a las deniciones del archivo, igual que el botn Run de DrRacket.
30
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
567
cuando se ejecute.
1
2
3
vector inmutable de cadenas inmutables, una por cada parmetro. Por ejemplo, considere
el siguiente programa:
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:
Los parmetros pasados al programa son: #("hola," "esta es" "una" "prueba")
31
32
Racket. Puede obtener una breve descripcin de todas sus posiblidades con
1
2
3
# lang racket
; hola . rkt
( display " Hola Mundo !\ n ")
Se compila as:
1
2
3
$ ./ ejecutable
Hola Mundo !
$
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
# 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:
34
Parte II
35
6 Elementos bsicos
A continuacin se presenta un recorrido por las principales y ms bsicas partes del lenguaje
Racket.
6.1. Comentarios
Los 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:
1
2
3
4
5
6
7
8
# lang racket
; Todos los programas Racket deben comenzar con esta lnea de arriba .
#|
|#
( display " Bueno , esto no es comentario , es cdigo \ n ") ;; Esto s ; -)
evaluar
<expresin>.
37
6 Elementos bsicos
1
2
3
4
5
6
7
8
9
10
11
12
13
( define mximo 3)
( define ( prefijo str )
argumento
( substring str 0 mximo )
)
> 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
6.2.1. Identicadores
Los 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:
\.
( ) [ ] { } , ' ` ; # |
variable-con-guiones, variable+con+ms-y-t
123abc, +-, variable-interrogativa???, 23..4, variable/dividida, etc.
Por lo dems, se pueden utilizar identicadores como
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:
38
(<identificador> <expresin>*)
donde la secuencia de expresiones determina el nmero de parmetros reales pasados a
la funcin referenciada por el identicador. Por ejemplo
pia).
(prefijo hola)
(hornear
string-append, substring,
etc.
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 bsicos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
2
3
4
5
6
7
8
6.4.2. and y or
y
or
y retorna
#t
(and <expresin>*)
La primera retorna
#f
#t
y retorna
#f
(or <expresin>*).
#t
#f,
and
Java ).
Ejemplo:
1
2
3
4
5
6
7
8
9
40
10
11
12
x < 1
x + 2
f (x) = 1
1 x < 0
2
x + 1 0 x
6.4.3. cond
Una forma de bloques condicionales anidadas (if anidados) es:
#t.
41
6 Elementos bsicos
Por ejemplo (ver la gura 6.1):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>
19
20
21
22
23
24
25
28
29
30
31
32
33
34
; -1 <x <0 : 1
; 0<x
: -x ^2+1
( define ( responder - ms s )
( cond
[( equal ? " hola " ( substring s 0 4) )
" hola , gusto de verte !"]
[( equal ? " adis " ( substring s 0 5) )
" nos vemos , que te vaya bien !"]
[( and ( equal ? " " ( substring s 0 1) )
( equal ? "?" ( substring s ( - ( string - length s ) 1) ) ) )
" No s "]
[ else " perdn , qu ?"]) )
18
27
x < -1: x +2
17
26
> ( responder - ms
" No s "
> ( responder - ms
" hola , gusto de
> ( responder - ms
" perdn , qu ?"
> ( responder - ms
" nos vemos , que
se cierre con un
y un
se cierre con un
corchetes junto a los parntesis hace del cdigo Racket ligeramente ms legible.
6.4.4. case
Los bloques
case
> ( case (+ 7 5)
42
secuencia de instrucciones,
let,
1
2
3
4
5
6
7
8
9
10
por lo que esas alternativas suelen bastar. Pero para aquellos casos en los que no, se
begin:
> ( 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 "
1 como:
(<expresin-de-funcin> <expresin>* )
La
<expresin-de-funcin>,
una funcin.
Por ejemplo:
43
6 Elementos bsicos
1
2
3
4
5
6
7
if
<expresin-de-funcin>
+).
primer elemento dentro de los parntesis debe ser una funcin. Por ejemplo, la siguiente
expresin:
> (1 2 3)
produce el error:
1
2
3
4
5
6
44
lambda
(+ 5 4)
Es 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
bloque lambda
45
define)1 ,
1
2
2
3
4
lambda,
lambda.
lambda,
> ( componer ( lambda ( s ) ( string - append " " s "!") ) " hola ")
" hola !!"
> ( componer ( lambda ( s ) ( string - append " " s "!?") ) " hola ")
" hola !?!?"
lambda
ciones:
1
2
3
4
5
6
7
8
9
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
1
2
3
4
46
( lambda ( s )
( string - append " " s "!") ))
> poner - admiracin
# < procedure : poner - admiracin >
47
48
8 Asignacin local
Hay al menos tres formas de hacer asignacin local en Racket: Con
let*.
define,
con
let
y con
8.1. define
Hagamos otra ampliacin de la sintaxis para los bloques de funciones:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
49
8 Asignacin local
8.2. let
Otra forma de hacer asignaciones locales, es con el bloque
bre
define
let.
Una ventaja de
let
so-
define.
Adems, con
define
let
let es:
(let ( { [<identificador> <expresin>] }* ) <expresin>+ )
La sintaxis de
<identificador>
y una
<expresin>
rodeadas por
corchetes, y las expresiones que van despus de las clusulas, son el cuerpo del
cada clusula, al
<identificador>
se le asigna el resultado de la
let,
<expresin>
let.
En
para ser
Por ejemplo:
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
let estn disponibles slo en el cuerpo del let, as que las clusulas de
let*, 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
51
9 Listas e Iteracin
En 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. Listas
Las 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
list:
> ( 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
list
sin parmetros:
empty
null
'()
(list)
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:
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 "
list-ref
para extraer el i-simo elemento de una lista (los ndices comienzan desde
54
9.1 Listas
append
reverse
member
list?
para vericar si un identicador se corresponde con una lista (que puede estar
vaca)
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
propias de los lenguajes funcionales, para recorrer y procesar secuencias (listas) de elementos.
9.2.1. map
La primera de ellas, es la funcin
los elementos de una lista, para generar otra lista. Por ejemplo:
1
2
3
4
5
6
7
8
9
andmap
ormap.
En sus formas
ms simples, ambas toman como parmetros una funcin y una lista. En el caso de la
primera, retorna
#t;
y devuelve
La funcin
ormap
es
andmap. ormap
devuelve
#t
si la funcin se evala a
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
#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. filter
La funcin
filter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
57
9 Listas e Iteracin
lista - nmeros )
" Esta funcin espera una lista de nmeros "
)))
22
23
24
25
26
27
28
29
30
31
32
33
9.2.4. for-each
Existe 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for-each:
La funcin
for-each,
a diferencia de
map,
for-each
58
ormap
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.
first
ms primitivos
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)
cons
cons? verica si un elemento es una lista no vaca (lo contrario de empty? y de null?)
Ejemplos:
1
2
3
4
5
59
9 Listas e Iteracin
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
9.3.1. Aplicacin
Teniendo a nuestra disposicin estas funciones de
bajo nivel
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
60
))
cons acepta dos parmetros, y el segundo no necesariamente debe ser una lista.
En el caso que como segundo argumento se le pase algo que no sea una lista, la funcin
cons devuelve un
Un Par
Par
Pareja.
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)
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
61
9 Listas e Iteracin
21
22
23
24
1
2
ms fcil de leer.
puntos
puntos
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
63
9 Listas e Iteracin
64
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
display,
retornar
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:
'(hola).
4. Dada una lista compuesta por cadenas, construir una cadena formada por cada cadena
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
display).
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
member).
#f
#t
si el
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 Iteracin
12. Dada una lista compuesta por tres puntos (un punto es una lista, ejemplo
un punto
y
#f
x 1, y 2)
retornar
#t
'(1 2)
es
en caso contrario (es equiltero si sus tres lados son iguales). NOTA : Frmula
(x1 , y1 )
(x2 , y2 ): d =
q
(x2 x1 )2 + (y2 y1 )2
13. Dada una lista compuesta por listas, retornar una lista compuesta por los elementos de
cada sublista. Ejemplo
'(hola mundo)
retornar 4.
15. Dada una lista compuesta por cadenas, retornar la lista compuesta por las cadenas
sin sus vocales. Ejemplo:
'(hola mundo)
retornar
'(hl mnd)
note que se
hola
se con-
'(h o l a). Note que no se piden los caracteres si no las letras en
forma de cadena.
17. Dada una lista compuesta por cadenas, ordenar dicha lista tomando como criterio la
longitud de las cadenas (No usar
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
values)
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 Recursin
10.1. Recursin por Posposicin de trabajo
En el caso del siguiente cdigo de la funcin
longitud,
posposicin de trabajo:
1
2
3
4
( define ( longitud L )
( cond
[( empty ? L ) 0]
[ else (+ 1 ( longitud ( rest L ) ) ) ]) )
Y al evaluar, por ejemplo,
1
2
3
4
5
6
7
8
->
=
=
=
=
=
=
=
se da este proceso:
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.
1
2
3
4
5
longitud
( define ( longitud L )
; funcin local longitud - aux :
( define ( longitud - aux L longitud - actual )
( cond
[( empty ? L ) longitud - actual ]
67
10 Recursin
[ else ( longitud - aux ( rest L ) (+ longitud - actual 1) ) ]) )
; este es el cuerpo de longitud , que llama a longitud - aux :
( longitud - aux L 0) )
6
7
8
1
2
3
4
5
6
->
=
=
=
=
=
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.1. Booleanos
El tipo ms simple de Racket es el
que son
booleano
lgico.
#t para verdadero y #f para falso (tambin se aceptan las formas #F y #T, pero las
1
2
3
4
#f:
boolean?
#t
> ( boolean ? 0)
#f
> ( boolean ? # f )
#t
A pesar de que se espera un valor de verdad en las expresiones de prueba de las construcciones
if, cond, and, or y otras, todos los valores posibles en Racket, excepto #f se evalan
como verdadero:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
69
#t
> ( mostrar - valor - de - verdad #\ a )
#t
11.2. Nmeros
A continuacin se presenta el tratamiento de los
nmeros
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
en Racket.
number?:
> ( 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. Clasicacin
Hay dos formas de clasicar nmeros en Racket: Por exactitud y por conjuntos.
nmero
nmeros exactos
es
exacto
inexacto.
son:
1. Los enteros
2. Los racionales
3. Los complejos con parte real exacta y parte imaginaria exacta
Los
70
nmeros inexactos
son:
11.2 Nmeros
1. Los reales de coma otante
2. Los complejos con parte real inexacta o parte imaginaria inexacta
Existen las funciones
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)
#f
Pueden tambin utilizarse las funciones
de un tipo a otro:
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
#e
#i:
> # e0 .2
1/5
> # i1 /5
0.2
> # i4 +5 i
4.0+5.0 i
Propagacin de la exactitud
se mantienen exactos tras los clculos y los inexactos se mantienen inexactos a travs de
los clculos:
71
x ) ) 5 8)
ZQRC
1
2
3
4
5
6
7
8
9
10
11
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
10,
pero puede
respectivamente:
11.2 Nmeros
11.2.3. Comparaciones
Los nmeros exactos pueden ser comparados con la funcin
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
por proximidad
en lugar
> (= 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 )
)
+inf.0/-inf.0
+nan.0/-nan.0 que resultan de clculos indeterminados como cero entre cero, innito
entre innito, cero por innito, innito menos innito, etc.
1
2
3
4
73
- 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 .0
Si 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
11.3. Caracteres
Un
caracter
gramacin como
Java ).
#\
1
2
3
4
> #\0
#\0
> #\ a
#\ a
74
11.3 Caracteres
5
6
7
8
9
10
> #\ newline
#\ newline
> #\ space
#\ space
> #\&
#\&
Java
C ),
char->integer
integer->char:
Si algn caracter no tiene una representacin imprimible, este siempre se puede mostrar
con la notacin Unicode tradicional de una letra
dos bytes:
1
2
3
4
75
11.4. Cadenas
Una
cadena
display
76
11.4 Cadenas
Ejemplos:
string
string-ref
string-length
Ejemplos:
1
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
inmutables,
objetos del programa. Pero si requerimos alterar una cadena durante la ejecucin, debemos
crear una
cadena mutable.
su contenido:
make-string
77
string->immutable-string
immutable? verica si un objeto es inmutable no slo las cadenas pueden ser mutables
.
string-copy!
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
78
11.4 Cadenas
string-ci=?, string-ci<?, string-ci<=?, string-ci>?, string-ci>=?
para hacer
1
2
3
4
5
6
7
8
9
10
11
serie de cadenas.
string->list
dena.
list->string
devuelve una nueva cadena mutable que contiene todos los caracteres
de la cadena proporcionada.
substring
proporcionada.
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
> ( string - append " Esta " " es una cadena " " unida " ( make - string 3 #\ -) )
" Esta es una cadena unida - - -"
> ( string - > list " cadena ")
(#\ c #\ a #\ d #\ e #\ n #\ a )
> ( list - > string '(#\ C #\ a #\ d #\ e #\ n #\ a ) )
" Cadena "
> ( substring "0123456789" 1 7)
"123456"
> ( substring "0123456789" 4)
79
"456789"
> ( substring "0123456789" 4 5)
"4"
[#x0,#xff]).
La funcin
byte?
1
2
3
4
5
6
cadenas de bytes,
comunicaciones de bajo nivel. Estas cadenas no tienen codicacin Unicode, sino ASCII.
En modo interactivo, se muestran como cadenas normales precedidas de un
que con las cadenas normales las cadenas Unicode son por defecto
#.
Y al igual
inmutables.
Cuando
bytes-ref
make-bytes devuelve una nueva cadena de bytes mutable, dada su longitud y un byte
de relleno.
bytes-set!
nuevo byte.
bytes?
Ejemplos:
1
2
3
4
5
6
7
8
80
11.6 Smbolos
9
10
11
12
13
14
15
16
17
18
otra - cadena 3 0)
otra - cadena 2 10)
otra - cadena 1 5)
11.6. Smbolos
Un
smbolo
es como una cadena inmutable, pero sin la posibilidad de acceder a sus carac-
teres. Su utilidad radica en que son buenos para servir como etiquetas o valores constantes,
o enumeraciones para las funciones.
Hay algunas funciones que sirven para manipularlos:
symbol?
string->symbol
symbol->string
Un smbolo se imprime como un identicador, pero puede estar compuesto por caracteres no
permitidos en los identicadores espacios en blanco y
( ) [ ] { } , ' ` ; # | \,
en cuyo caso, se imprime como una secuencia de caracteres, encerrados en barras verticales:
||.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
# lang racket
; smbolo . rkt
81
1
2
3
4
5
6
7
8
9
10
11
82
palabras clave
#:palabra.
Su utilidad se explica en la
pares y listas
mutabilidad
inmutables.
Pero tambin
de los pares:
pair?
list?
mcons
mpair?
set-mcar!
set-mcdr!
mcar
mcdr
mente.
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
83
11.9. Vectores
Un
vector es un arreglo de longitud ja de valores arbitrarios. A diferencia de una lista, que
es una lista lineal de nodos enlazados en memoria, un vector soporta acceso a sus elementos
lectura y escritura en tiempo constante. Esa es bsicamente su mayor diferencia.
Otra diferencia, es que al imprimirse, un vector se muestra como una lista precedida por
un
#.
vector-ref
list->vector
vector->list
vector-set!
84
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> #(1 " dos " 3.1) ;; Esto genera un nuevo vector inmutable
#(1 " dos " 3.1)
> ( define v #(1 " dos " 3.1) )
> ( vector - ref v 0)
1
> ( vector - ref v 2)
3.1
> ( vector - > list v)
(1 " dos " 3.1)
> ( list - > vector '(" a " " b " " c ") )
#(" a " " b " " c ")
> ( vector 1 2 3)
#(1 2 3)
> ( define v ( vector 0 1 2) )
> ( vector - set ! v 1 " uno ")
> v
#(0 " uno " 2)
Tambin hay algunas otras funciones para manipular vectores mutables e inmutables de
manera parecida a las listas:
make-vector
valor de relleno.
vector-immutable
vector->immutable-vector
vector-copy!
tabla hash
mapeo
de
claves,
valores
de acceso a los vectores que siempre es constante y a diferencia del de las listas que es
linealmente creciente dependiendo de la posicin del elemento a accesar.
85
hash?
make-hash
mutable
vaca.
hash-set! agrega una asociacin dentro de una tabla hash mutable, sobreescribiendo
cualquier asociacin previa para la clave indicada.
hash-set toma una tabla hash inmutable, una clave y un valor, y devuelve otra tabla
hash inmutable equivalente a la anterior ms la nueva asociacin entre la clave y el
valor indicados.
hash-ref devuelve el valor al que corresponde una clave indicada, dentro de una tabla
hash indicada, si es que existe.
hash-remove
hash-count
tenidos en ella.
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
11.11. Void
Eventualmente, necesitamos construir funciones
emos que se ejecuten por sus efectos colaterales, como las funciones
86
display, printf,
11.11 Void
otras. En esos casos, utilizamos el procedimiento especial
especial
1
2
3
4
5
6
7
#<void>:
void
> ( void )
> ( begin
" Este bloque no devuelve nada ..."
( void )
)
> void
# < procedure : void >
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
> ;;; Tambin sirve cuando slo queremos la parte verdadera ( o falsa ) de un
if : ;;;;;;;;;;;
> ( define ( mostrar - si - es - entero n )
( if ( integer ? n )
( printf " El parmetro es un entero \ n ")
( void )
)
)
> ( mostrar - si - es - entero 3)
El parmetro es un entero
> ( mostrar - si - es - entero 5.7)
> ( mostrar - si - es - entero " hola ")
> ( mostrar - si - es - entero -3)
El parmetro es un entero
> ( void ? ( printf )
#t
> ;;; Compare estas dos ejecuciones : ;;;;;;;;;;;;;;;;;;;;;;;
> ( for - each display '(1 2 3) )
123
> ( map display '(1 2 3) )
123(# < void > # < void > # < void >)
87
88
cualquier nmero de parmetros, pero una llamada especca siempre especica un nmero
jo de parmetros reales. Como resultado, no se puede pasar directamente una lista de
argumentos a una funcin:
1
2
3
4
5
>
+ espera
apply:
La funcin
la funcin
1
2
3
4
5
6
7
8
Y el resultado equivale a:
lambda
con
lambda
es:
89
1
2
3
4
5
6
7
8
9
10
11
12
13
14
> (( lambda x x ) 1 2 3)
(1 2 3)
> (( lambda x x ))
()
> ( define mayor - valor - absoluto
( lambda lista
( apply max ( map abs lista ) )
)
)
> ( mayor - valor - absoluto -5 -4 -3 -2 -1 0 1 2 3)
5
es un identicador que ser una lista con todos los parmetros reales restantes, si los hubiera.
Ejemplo:
1
2
3
90
lambda
[<identificador-de-parmetro> <valor-por-defecto>] es
opcional. Cuando el argumento no es indicado en la llamada, la expresin <valor-por-defecto>
Un parmetro de la forma
produce un valor que se asigna como parmetro real. Esta expresin puede hacer referencia
a cualquier parmetro precedente. Y todos los parmetros siguientes a uno opcional, deben
ser opcionales; no se puede denir un parmetro obligatorio despus de uno opcional en
una misma funcin.
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
91
<palabra-clave> <identificador-de-parmetro> es
<palabra-clave>. La posicin del binomio <palabra-clave>
<identificador-de-parmetro> en la lista de parmetros reales no importa para hacer
palabra clave
En este momento vale la pena decir que existen cuatro tipos de parmetros:
1.
4.
Los parmetros obligatorios por palabra clave. Con estos, el parmetro real, debe ir
precedido por una palabra clave y se corresponder con el parmetro formal que est
precedido por esa misma palabra clave.
Los parmetros opcionales por palabra clave. En este caso,
palabra clave.
el parmetro real, si se
Tambin, hay que agregar que una vez que se dene un parmetro opcional (por posicin
o por palabra clave), los parmetros siguientes deben ser todos opcionales.
Ejemplos:
92
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
case-lambda,
case-lambda
tiene la sintaxis:
( case - lambda
[ < parmetros - formales - case > < expresiones - cuerpo >+ ]*
)
< parmetros - formales - case > ::= ( < identificador - parmetro >* ) |
< lista - de - parmetros > |
( < identificador - parmetro >+ . < lista - de parmetros > )
[ <parmetros-formales-case> <expresiones-cuerpo>+ ],
(lambda <parmetros-formales-case> <expresiones-cuerpo>+)
case-lambda
es como aplicar un
lambda
para el
primer caso en que coincida el nmero de parmetros reales con los formales.
93
case-lambda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure-arity, y procedure-arity-includes?.
arity-at-least.
Tambin
arity-at-least
Esta estructura tiene la denicin (vase el captulo 13):
donde
value
es un entero no negativo.
Esto puede sonar muy extrao en este momento, pero no es tan complicado, as que mejor
siga leyendo el resto de la seccin.
procedure-arity
La funcin
Su sintaxis es:
94
ros nicamente.
Una instancia de la estructura transparente arity-at-least, lo que signica que
<funcin> acepta un mnimo nmero de parmetros, y ese mnimo es el valor (entero
no negativo) del campo value de la estructura devuelta.
Una lista de enteros no negativos e instancias de
que
<funcin>
arity-at-least,
lo que signica
elementos de la lista.
Ejemplos:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
procedure-arity-includes?
Tiene la sintaxis:
1
2
3
4
5
6
7
8
9
10
11
95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
quotient/remainder
quotient y remainder
1
2
3
4
5
6
7
8
9
> ( quotient 13 3)
4
> ( remainder 13 3)
1
> ( quotient / remainder 13 3)
4
1
Visualmente, los dos valores aparecen en lneas diferentes; algortmicamente hablando, esto
en consistente con el hecho que los algoritmos puede producir mltiples valores de salida,
as como pueden tomar mltiples valores de entrada.
96
12.3.1. values
La funcin
1
2
3
4
5
6
values
> ( values )
> ( values " a " 1 #\ a )
"a"
1
#\ a
Eventualmente nuestras funciones deben devolver dos o ms valores simultneamente. En
esos casos, se podra optar por devolver una lista o vector con los valores correspondientes;
pero usar la funcin
values
se devuelven los resultados del clculo y no una lista con los resultados.
12.3.2. define-values
El bloque
1
2
3
4
5
6
7
<expresin>
let-values
1
2
3
4
5
6
en una denicin,
97
12.4. Asignaciones
En ciertos casos
desesperados,
1
set!
set!-values.
La sintaxis es:
Como ya habr notado el lector, las asignaciones de variables, no suelen necesitarse en el paradigma
funcional.
98
N.
Es decir:
retornar
y como segundo
N.
2. Elaborar una funcin cuya restriccin es que tiene que recibir parmetros indenidos
es decir el nmero de parmetros puede ser variable, para este ejercicio se pide que
si se recibe un nmero tiene que retornar el nmero, si recibe dos nmeros tiene que
retornar el mayor de ambos, si son tres nmeros retornar las dos races de la ecuacin
cuadrtica, en la que cada nmero ser el coeciente literal de
Ax2 + Bx + C = 0.
3. Elaborar una funcin que reciba de parmetro una cadena y un carcter, este carcter
ser el que se busque en la cadena y por cada ocurrencia de este carcter en la cadena
se sustituir por un espacio en blanco. La restriccin de este ejercicio es que la cadena
y el carcter pueden ser pasados de parmetro en diferente orden y la funcin deber
funcionar correctamente.
4. Elaborar una funcin que reciba de parmetro una lista de smbolos que representen
los atributos de un automvil y una lista de smbolos con los valores de estos atributos. La funcin retornar una lista que contenga pares, cada par contendr smbolos,
indicando su atributo y su valor.
Ejemplo: Si ingresamos lo siguiente:
> (automovil '(Hatchback Suzuki Forza1 Rojo si Manual) '(Tipo Marca Modelo
Color A/C Transmisin))
el resultado ser:
99
retornar una lista vaca, si hay un solo parmetro retornar el punto en el plano cartesiano en forma de par , si recibe dos puntos retornar la distancia entre los dos puntos,
si son tres puntos retornar el rea del tringulo formado.
9. Elaborar una funcin que reciba 2 nmeros enteros
pares donde la primera posicin ser el nmero y la segunda una cadena con si o no
que indicar si el nmero es primo o no, se tomarn todos los nmeros comprendidos
en el rango
100
puedan
make-<nombre-estructura>
turas del nuevo tipo, y toma tantos parmetros como campos tenga el tipo.
<nombre-estructura>?
<nombre-estructura>-<nombre-campo>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
101
inmutables.
( struct - copy < nombre - estructura > < expresin - de - estructura >
{ [ < nombre - campo > < expresin - para - un - campo > ] }*
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
tura, que es un tipo de estructura que extiende a otro tipo, o que se deriva de otro.
La sintaxis es:
102
Vale la pena mencionar que cuando se trata de estructuras derivadas, hay una convencin
de nombres en Scheme:
derivada,
base:derivada:descendiente,
base,
debera
descendiente,
base:derivada.
Y si de esta,
su nombre formal
debera
ser
as:
103
opaca,
transparente,
se imprime como
transparente
es:
1
2
3
4
5
6
sulamiento
encap-
set-<nombre-estructura>-<nombre-campo>!;
la estructura.
Ejemplo:
1
2
3
4
5
6
7
8
9
10
11
104
parente :
1
2
3
4
5
6
7
8
9
10
11
mutable
y como
trans-
105
106
respectivamente , luego
retornar una lista con los 3 puntos ordenados de menor a mayor bajo el criterio de
la distancia al origen.
3. Elaborar una funcin que reciba como parmetro una lista de estructuras de tipo
fecha, y que retorne la lista ordenada de fecha anterior a posterior. Si algn elemento
que est en la lista no es de tipo fecha, retornar una lista nula.
4. Elaborar una funcin que reciba una cadena que corresponda a un nombre de persona,
y un nmero indicando la edad de la persona, y como ltimo parmetro el nmero de
DUI(cadena) de la persona, la funcin deber de retornar una estructura transparente
de tipo persona, pero con la condicin que si la persona es menor de edad el campo
de DUI estar vaco pudindose modicar en el futuro.
5. Elabore una funcin que reciba como parmetro una estructura de tipo persona, la
funcin deber de retornar una estructura de tipo empleado (derivada de persona) y
para ello se deber de capturar en tiempo de ejecucin el NIT(cadena) y el nmero
de telfono (cadena).
6. Elaborar un funcin que reciba como parmetro una lista de estructuras de tipo persona, dicha funcin deber retornar la lista de estructuras ordenada alfabticamente
por nombre de persona. Note que nombres como scar , van junto con los nombres
con letra inicial o y no antes de los nombres con inicial a , ni despus de los nombres
con inicial z .
7. Elaborar una funcin que reciba de parmetro un conjunto de puntos en forma de
pares, la funcin deber de retornar un vector ordenado de mayor a menor distancia
al origen, que contenga los puntos pero con una estructura
un campo el par
(x . y)
puntoD,
la cual tiene en
107
108
14 Mdulos Funcionales
As como en otros lenguajes de programacin, en Scheme se pueden denir
cionales.
clases
Estos
mdulos
equivalen a las
bibliotecas de funciones
Mdulos Fun-
bibliotecas de objetos/-
de otros lenguajes.
En general un
mdulo sirve para encapsular cierto cdigo, sin que el usuario del mismo tenga
#lang racket es un
.rkt (.ss o .scm).
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
# lang racket
; pastel . rkt
;; Vuelve ' pblica ' la definicin de ' imprimir - pastel ' y ' nmero - por defecto ':
( provide imprimir - pastel nmero - por - defecto )
;; Estas
( define
( define
( define
( define
109
14 Mdulos Funcionales
Entonces, desde otro archivo en el mismo directorio, se puede invocar la funcin
imprimir-pastel,
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
# lang racket
; mostrador -de - pasteles . rkt
( define secuencia - de - enteros
( lambda ( num - elementos [ inicio 0] [ paso 1])
( 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 ")
)
))
( require " pastel . rkt ")
; Imprime un pastel de ' nmero - por - defecto ' candelas :
( imprimir - pastel )
( printf " El nmero por defecto de candelas es : ~ a \ n " nmero - por - defecto )
; Imprime 8 pasteles desde 0 hasta 7 candelas :
( for - each imprimir - pastel ( secuencia - de - enteros 8) )
Para ejecutarlo, evaluamos el comando:
$ racket mostrador-de-pasteles.rkt
Otro detalle importante, es que cuando se invoca (con
require)
a un mdulo funcional,
este es ejecutado, de tal manera que se realizan todas las deniciones en l, y se ejecutan
todas las expresiones que contenga.
provide:
estructura?, estructura-campo1,
110
biblioteca.rkt.
15 Entrada y Salida
Aqu se describe lo bsico para comprender las posibilidades de
Entrada y Salida
en
Scheme.
En Scheme, un
puerto
write.
display.
caracter. Es una forma muy legible de mostrar los datos, pero es menos precisa sobre
el tipo de dato que se muestra.
111
15 Entrada y Salida
write
display
Finalmente, la funcin
printf
valores. Estos otros valores, se ingresan como parmetros extra en la funcin, y en la cadena
de formateo, como
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
112
~a -> display
~s -> write
Existen muchos mecanismos para leer datos en Scheme. De hecho, el lector de Scheme (
Reader ),
es un
es decir, un programa
(current-input-port)
(read-char {<entrada>}? ):
por defecto es
UTF-8.
(read-byte {<entrada>}? ):
ascii.
(read-line {<entrada> {<modo>}? }? ): Lee una cadena que va desde el punto actual del cursor hasta el prximo n de lnea. Lo que se considera como n de lnea
depende del segundo parmetro opcional:
\n.
Este es el
'return
\r.
Este es el
<cuenta>
caracteres.
113
15 Entrada y Salida
En todos los casos, pueden devolver el objeto especial
eof-object?.
eof
(read {<entrada>}? )
La funcin
read
(, [
{,
), ]
},
#t, #T, #f
#(, #[
#{,
#F,
.
#\
#
# % inicia un smbolo (lo mismo que si no coincide con ningn otro de estos patrones).
#:
#|
#i, #e, #x, #o, #d, #b, #I, #E, #X, #O, #D, #B,
|#).
#hash
#sx inicia una expresin de racket (Scheme eXpression ). Esta opcin es muy til para
convertir texto en cdigo fuente. Esto se aplica en el cap Evaluacin Dinmica.
Ejemplos (en todos ellos, tan slo la ltima lnea es la respuesta de la expresin, y todas
las lneas entre la expresin y la respuesta fue introducida por el teclado):
Resumida aqu
114
> ( read )
3
3
> (+ 2 ( read ) )
4
6
> (+ 1 ( read ) )
# xf
16
> ( string - append " Hola , " ( read ) )
" Eduardo "
" Hola , Eduardo "
> ( string - append " Hola , " ( read ) )
#| este es un comentario muy largo
que tiene varias lneas y que sern ignoradas por el lector |#
" Eduardo "
" Hola , Eduardo "
> ( rest ( read ) )
(1 " cadena " ; Este es un comentario de una lnea
3.45 #(1 2 3)
; otro comentario
)
(" cadena " 3.45 #(1 2 3) )
Consulte la seccin
abrir
cerrar.
La funcin de apertura,
depende del tipo particular de puerto que se necesite abrir, pero la funcin de cierre slo depende de la direccin del ujo; en todos los casos son
close-input-port y close-output-port.
input-port?
output-port?
port?
da/escritura.
port-closed?
115
15 Entrada y Salida
eof-object? verica si el parmetro proporcionado (que debera provenir de la lectura
de un ujo de entrada/lectura) indica que ya se ha acabado el ujo (puede implicar
una conexin terminada o el n de un archivo).
flush-output
15.3.1. Archivos
open-input-file. Para abrir un
archivo para escritura, se usa la funcin open-output-file. Para abrir un archivo para
lectura y escritura se usa la funcin open-input-output-file.
Para abrir un archivo para lectura, se utiliza la funcin
Ejemplo:
1
2
3
4
5
6
7
> ( define salida ( open - output - file " archivo . txt ") )
> ( display " Hola " salida )
> ( close - output - port salida )
> ( define entrada ( open - input - file " archivo . txt ") )
> ( read - line entrada )
" Hola "
> ( close - input - port entrada )
A continuacin se describe la sintaxis de las funciones de apertura de puerto de archivo:
open-input-file
La sintaxis completa de la funcin open-input-file es:
(open-input-file <ruta> {#:mode { 'binary | 'text } }? ), donde la opcin por defecto para el parmetro #:mode es 'binary.
open-output-file
La sintaxis completa de la funcin
open-output-file
es:
(open-output-file <ruta>
{#:mode { 'binary | 'text } }?
{#:exists { 'error | 'append | 'update | 'can-update | 'replace | 'truncate |
'must-truncate } }? ), donde el parmetro #:exits indica el comportamiento a seguir
cuando el archivo indicado en <ruta> ya existe. Por defecto se toma 'error. Su signicado
es:
'error
116
'append
'update
existe.
'replace
'truncate
'must-truncate borra el
no existe.
open-input-output-file
open-input-output-file es:
(open-input-output-file <ruta>
{#:mode { 'binary | 'text } }?
{#:exists { 'error | 'append | 'update | 'replace | 'truncate } }? ), donde el
parmetro #:exits indica el comportamiento a seguir cuando el archivo indicado en <ruta>
ya existe. Por defecto se toma 'error. Su signicado es:
La sintaxis completa de la funcin
'error
'append
'update
'replace
'truncate
Ejemplo
Este es un programa que lee e imprime en pantalla todas las lneas de un archivo proporcionado como parmetro, anteponindoles el nmero de lnea correspondiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# lang racket
; lee - lneas . rkt
( define ( mostrar - lneas nombre - archivo )
( define ( aux flujo nmero -de - lnea )
( let ([ lnea ( read - line flujo ) ])
( if ( eof - object ? lnea )
( close - input - port flujo )
( begin
( printf "~ a : ~ s \ n " nmero -de - lnea lnea )
( aux flujo ( add1 nmero - de - lnea ) )
)
)
)
)
( if ( file - exists ? nombre - archivo )
117
15 Entrada y Salida
( aux ( open - input - file nombre - archivo ) 1)
( error ( string - append " No existe el archivo " nombre - archivo ))
)
17
18
19
20
21
22
23
24
25
26
27
Procesamiento automatizado
Existen accesoriamente, dos funciones para realizar de manera automatizada la apertura
de un archivo y pasarle el puerto abierto resultante a una funcin. Estas funciones son:
<ruta>
<procedimiento>
debe ser
una funcin que reciba como nico parmetro obligatorio un puerto de entrada o de salida,
respectivamente.
El comportamiento es el siguiente:
1. Se intenta abrir el archivo indicado en
<ruta>
<procedimiento>
<procedimiento>
4. Finalmente, el resultado de
o
La utilidad de estas funciones es que las funciones que contienen la lgica del procesamiento
de los ujos (de entrada o de salida) no se mezclen con
es un procedimiento que depende del tipo de puerto.
Considere la siguiente variante del cdigo anterior:
1
2
# lang racket
; lee - lneas2 . rkt
118
15.3.2. Cadenas
As como un archivo puede
abrirse
hacer lo mismo con las cadenas de texto. Las funciones para abrir un puerto de cadena son:
open-input-string
open-output-string.
puerto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
> ( define cadena - fuente " Esta es una lnea de una cadena \ nEsta es la
segunda \ ny la tercera .")
> ( define p - lectura ( open - input - string cadena - fuente ) )
> ( read - line p - lectura )
" Esta es una lnea de una cadena "
> ( read - line p - lectura )
" Esta es la segunda "
> ( read - line p - lectura )
" y la tercera ."
> ( read - line p - lectura )
# < eof >
> ( close - input - port p - lectura )
>
>
> ( define p - escritura ( open - output - string ) )
119
15 Entrada y Salida
15
16
17
18
19
20
21
22
23
24
en forma de cadena.
las conex-
tcp-accept
tcp-connect
tcp-close
acepte
tcp-listen.
Ejemplo:
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
# lang racket
; comunicacion . rkt
( provide hablar - inmediato )
( define hablar - inmediato
( lambda ( puerto - salida cadena . parmetros )
( apply fprintf ( cons puerto - salida ( cons cadena parmetros ) ) )
( flush - output puerto - salida )
))
# lang racket
; servidor . rkt
( require " comunicacion . rkt ")
( define servidor ( tcp - listen 65432) ) ;; Aqu va el puerto de escucha . Falla
si est ocupado .
( define ( escuchar - aux entrada salida )
( let ([ lnea ( read - line entrada ) ])
120
1
2
3
4
5
6
7
( define ( escuchar )
( define - values ( entrada salida ) ( tcp - accept servidor ) )
( printf " Este es el servidor : Conexin aceptada \ n ")
( hablar - inmediato salida " Hola , este es su amigo el Servidor , cmo est
?\ n ")
( escuchar - aux entrada salida )
( printf " Este es el servidor : Conexin terminada \ n ")
( escuchar )
)
( escuchar )
# lang racket
; cliente . rkt
( require " comunicacion . rkt ")
;; La IP del servidor ( o su nombre de dominio ) y el puerto
( define - values ( lectura escritura ) ( tcp - connect " localhost " 65432) )
121
15 Entrada y Salida
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
37
38
39
40
41
( define ( comunicarse )
( let ([ comando ( read - line ) ])
( if ( equal ? " salir " comando )
( begin
( close - output - port escritura )
( exit )
)
( if ( port - closed ? escritura )
( begin
( printf " El puerto ya se cerr \ nSaliendo ...\ n ")
( exit )
)
( hablar - inmediato escritura "~ a \ n " comando )
)
)
)
( comunicarse )
)
( define ( escuchar )
( let ([ mensaje ( read - line lectura ) ])
( if ( eof - object ? mensaje )
( void )
( begin
( printf "~ a \n > > " mensaje )
( escuchar )
)
)
)
)
( void ( thread escuchar ) )
( comunicarse )
predeterminados:
(current-input-port)
(current-output-port)
(current-error-port)
Para cambiar los puertos por defecto, se pueden usar estas mismas funciones con un
parmetro puerto:
122
(current-output-port <p>)
(current-error-port <p>)
<p>.
<p>.
<p>.
123
15 Entrada y Salida
124
#\u0042.
#\u0040
persona
persona
#t
informacin alguna.
125
15 Entrada y Salida
11. Elaborar un programa que reciba de parmetro el nombre de un archivo de texto, dicho
archivo debe contener en cada lnea una serie de palabras. La primera representa
el nombre de un continente y las dems representan nombres de los pases de ese
continente, se pide leerlos del archivo y mostrarlos en la salida estndar en forma de
pares que contengan una cadena con el nombre del continente y un vector de cadenas
con los nombre de los pases en el archivo. Los vectores debern estar ordenados
alfabticamente y los pares debern mostrarse tambin ordenados por el nombre del
continente. Si el archivo no existe retornar un mensaje de error.
12. Elabore un programa que realice la funcin de buscar una palabra en un archivo de
texto. El programa recibir de parmetro el nombre del archivo, pero pedir en tiempo
de ejecucin una palabra a buscar y si la encuentra, mostrar un mensaje indicndolo
junto con la la y la columna en la que la encontr. Si no la encontr, mostrar el
mensaje correspondiente. Si el archivo no existe mostrar un mensaje de error.
13. Elaborar una funcin que reciba como primer parmetro el nombre de un archivo
origen.txt y como segundo parmetro el nombre de un archivo destino.txt . La
funcin deber copiar la ltima letra del archivo origen.txt en la primer posicin
del archivo destino.txt , la penltima letra del archivo origen.txt en la segunda
posicin del archivo destino.txt y as sucesivamente.
126
16 Excepciones
lanza una excepcin. Y a
atrapada , se gestionar imprimiendo en la salida estndar de
1
2
3
4
5
6
7
8
9
10
11
12
> (/ 100 0)
. . /: division by zero
> ( car 35)
. . car : expects argument of type < pair >; given 35
> ( define p ( open - input - string " Esta es la cadena fuente ") )
> ( read - string 5 p )
" Esta "
> ( close - input - port p )
> ( read - string 5 p )
. . read - string : input port is closed
Para
Y funciona de la siguiente manera: Cuando aparece una forma como esta en el curso actual
<exp-cuerpo>. Si este
cdigo lanza alguna excepcin, se llama la primera funcin <f-evaluadora>. Si esta se
evala a verdadero, se ejecuta la correspondiente <f-manejadora> y su resultado ser el
resultado del bloque with-handlers. Si <f-evaluadora> se evala a falso, se probar con
la siguiente <f-evaluadora> si la hay, y as sucesivamente. Si ninguna <f-evaluadora>
resulta en verdadero, la excepcin ser relanzada para que otro bloque with-handlers de
obligatorio que ser el valor que represente a la excepcin lanzada en el cuerpo. Tpicamente
ser una instancia de alguna estructura derivada de
exn:fail
Ejemplo:
127
16 Excepciones
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
error
1
2
3
4
5
6
1
2
3
4
5
6
7
exn:fail:
raise
excepciones
error),
exn:fail
o de alguna de
costumbre.
> ( raise 2)
uncaught exception : 2
> ( with - handlers ([( lambda ( v ) ( equal ? v 2) ) ( lambda ( v ) ' dos ) ])
( raise 2) )
dos
> ( with - handlers ([( lambda ( v ) ( equal ? v 2) ) ( lambda ( v ) ' dos ) ]
[ string ? ( lambda ( e ) ( printf " La excepcin es una cadena \
n ") ) ])
128
129
16 Excepciones
130
dinmico,
eval
apostrofada
un caracter apstrofo ' ) y la evala. Otra forma de describir el parmetro es como una
lista de identicadores y otros valores primitivos.
Por ejemplo:
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
131
eval
read
expresin de racket vlida, en una funcin que evala esa expresin. A continuacin se
presentan tres ejemplos:
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
132
Por convencin, los nombres de las clases en Scheme, terminan con el caracter %. La clase
raz integrada del lenguaje se llama
object %.
<identificador>
clase que implemente la interface. De no ser as, se lanzar un error al momento de evaluar
la denicin de la clase en cuestin.
class*:
( class* <superclase> (<interface>*) <declaracin-o-expresin>* )
133
lambda
vez.
La forma de
<parmetro-de-inicializacin>
18.4. Mtodos
18.4.1. Denicin e Invocacin de Mtodos
Dentro del cuerpo de una clase, en su seccin de deniciones, se denen los mtodos de la
clase con el bloque:
1
2
3
4
define/public
( begin
( public < nombre - mtodo >)
( define < nombre - mtodo > <exp - lambda_con_PARMETROS_y_EXP - CUERPO > )
)
El bloque
pblicas
public
sirve para indicar todos los identicadores de las funciones que sern
provide
para hacer
visibles o pblicos
ciertos identicadores
de los mdulos).
Para invocar un mtodo de un objeto, se utiliza el bloque
send:
define/override:
(define/override (<nombre-mtodo> <parmetros>* ) <exp-cuerpo>* )
Este bloque
1
2
3
4
define/override
( begin
( override < nombre - mtodo >)
( define < nombre - mtodo > <exp - lambda_con_PARMETROS_y_EXP - CUERPO > )
)
El bloque
override
sobreescritos
134
sirve para indicar todos los identicadores de las funciones que sern
en esta clase.
breescritos
define/override-final
so-
define/public-final
heredado):
1
2
3
4
( begin
( public - final < nombre - mtodo >)
( define < nombre - mtodo > <exp - lambda_con_PARMETROS_y_EXP - CUERPO > )
)
y
1
2
3
4
( begin
( override - final < nombre - mtodo >)
( define < nombre - mtodo > <exp - lambda_con_PARMETROS_y_EXP - CUERPO > )
)
Los bloques
public-final
override-final
sobreescritos
init
new, pero pasando los parmetros con sus respectivos nombres de parmetro formal:
(new <nombre-clase> <parmetro-real>* )
bloque
donde:
135
A y estos
(super-new).
cuando en
se encuentre la llamada a
init).
init),
y una
Entonces la instanciacin
el bloque:
(super-new <parmetro-real>* )
interface?
object=?
is-a?
subclass?
la clase proporcionada.
implementation? toma un valor y una interface y verica si el valor es una clase que
implementa la interface proporcionada.
implementation-extension?
method-in-interface?
alguna de sus ancestros) contiene un miembro con el mismo nombre que el smbolo.
interface->method-names
object-method-arity-includes?
136
18.7 Ejemplos
18.7. Ejemplos
Este es un ejemplo sobre denicin de clases y mtodos:
1
2
3
4
5
6
# lang racket
; cola . rkt
;; Definicin de una clase Cola
( define cola %
( class object %
8
9
( define elementos '() ) ;; Este valor es " privado " , dentro de la clase .
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
cola %:
137
5
> ( send colita sacar )
1234
> ( send colita tamao )
4
> ( send colita sacar )
"1"
Ejemplo para aclarar el signicado de
1
2
3
4
5
6
# lang racket
; pila . rkt
;; Definicin de una clase Pila
( define pila %
( class object %
( super - new )
8
9
10
11
12
13
14
15
16
( public meter ) ;; ' public ' y ' define ' con ' lambda ' separados
( define meter
( lambda ( nuevo - elemento )
( set ! elementos ( cons nuevo - elemento elementos ) )
)
)
17
18
19
20
21
22
23
( define / public ( sacar ) ;; ' public ' y ' define ' juntos
( if ( empty ? elementos )
( error " Intento de extraer un elemento de una Pila vaca !")
( let ([ e ( first elementos )]
[ lista ( rest elementos ) ])
( set ! elementos lista )
e
)
)
)
24
25
26
27
28
29
30
31
32
33
34
35
36
1
2
3
define/public:
138
pila %:
18.7 Ejemplos
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
>
0
>
>
1
>
9
>
0
>
>
( for - each ( lambda ( e ) ( send pilita meter e ) ) '( cos sqrt 3 " hola ") )
(( lambda ( pila )
( define ( sacar - todo p )
( if ( positive ? ( send p tamao ) )
( begin
( printf " Elemento : ~ a \ n " ( send p sacar ) )
( sacar - todo p )
)
( void )
)
)
( sacar - todo pila )
)
pilita
)
Elemento : hola
Elemento : 3
Elemento : sqrt
Elemento : cos
139
140
Parte IV
141
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# lang racket
; hola - mundo . rkt
; invocar al mdulo gui
( require racket / gui )
; Crear una ventanta
( define ventana ( new frame % [ label " Hola Mundo !"]) )
; Crear y ponerle un objeto ' message %' a la ventana
( define mensaje ( new message % [ parent ventana ]
[ label " Esta es una etiqueta con un poco de texto de
prueba \ nen dos lneas "]) )
; Mostrar la ventana al usuario
( send ventana show # t )
143
racket tradicional:
$ gracket hola-mundo.rkt
Existen varios mecanismos para manejar eventos. Entre ellos, algunos objetos, permiten
indicar un procedimiento de
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
callback
# lang racket
; eventos -1. rkt
( require racket / gui )
( define ventana ( new frame % [ label " Mi primer evento !"]) )
( define mensaje ( new message % [ parent ventana ]
[ label " Los eventos de los botones son ..."]) )
( new button % [ parent ventana ]
[ label " Mostrar respuesta "]
; Funcin a invocar cuando se presione el botn .
; Debe ser una funcin binaria , recibe una referencia al botn ,
; y una instancia ' control - event %'.
[ callback ( lambda ( botn evento )
; Los objetos ' message %' tienen un mtodo 'set - label '
144
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
# lang racket
; eventos -2. rkt
( require racket / gui )
( define ventana ( new frame % [ label " Mi segundo evento !"]) )
( define mensaje ( new message % [ parent ventana ]
[ label " Los eventos de los botones son ..."]) )
; Se est mostrando la respuesta ?
( define respuesta - mostrada #f )
( define mi - botn
( new button % [ parent ventana ]
[ label " Mostrar respuesta "]
[ callback ( lambda ( botn evento )
( if respuesta - mostrada
( begin
( send mensaje set - label " Los eventos de los
botones son ...")
( send mi - botn set - label " Mostrar respuesta ")
( set ! respuesta - mostrada # f )
)
( begin
( send mensaje set - label " sencillos :) ")
( send mi - botn set - label " Ocultar respuesta ")
( set ! respuesta - mostrada # t )
)
)
145
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
callback
# lang racket
; eventos -3. rkt
( require racket / gui )
( define ventana ( new frame % [ label " Mltiples eventos "]) )
( define ( funcin - manejadora b c )
( if ( object =? b botn1 )
( send mensaje set - label " Se presion el botn 1")
( send mensaje set - label " Se presion el botn 2")
)
)
( define botn1 ( new button %
[ parent ventana ]
[ label " Botn 1"]
[ callback funcin - manejadora ]
))
( define mensaje ( new message % [ parent ventana ]
[ label " An no se ha presionado ningn botn "]) )
( define botn2 ( new button %
146
24
25
26
27
28
29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
dialog %:
# lang racket
; dialogo . rkt
( require racket / gui )
; Ventana principal
( define ventana ( new frame % [ label " Inicio de sesin "]) )
( define datos ( new message %
[ label " An no ha iniciado sesin "]
[ parent ventana ]
[ auto - resize # t ]
))
( define lanzar
( new button %
[ parent ventana ]
[ label " Iniciar sesin "]
[ callback
( lambda ( b c )
( send ventana - de - dilogo show # t )
( send datos set - label
( string - append " Usuario : '"
147
))
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
)]
51
52
53
1
2
# lang racket
; text - field . rkt
148
149
54
55
56
57
58
59
19.6. Pneles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# lang racket
; pneles . rkt
( require racket / gui )
( define ventana ( new frame % [ label " Pneles horizontales "]) )
( define mensaje ( new message %
[ parent ventana ]
[ label " Pneles horizontales "]
[ auto - resize # t ]
))
;( define panel ( new horizontal - pane % [ parent ventana ]) )
( define panel ( new horizontal - panel % [ parent ventana ]) )
#|
La diferencia entre ' pane %' y ' panel %' es que
' pane %' slo sirve para administrar la distribucin
de los dems controles , no puede ser ocultado o deshabilitado ,
150
19.6 Pneles
20
21
22
23
24
25
26
27
28
29
30
event )
set - label " Clic del botn izquierdo ") ) ])
event )
set - label " Clic del botn derecho ") ) ])
31
32
33
151
152
1
2
3
4
5
6
7
8
9
10
11
# lang racket
; controles . rkt
( require racket / gui )
( define ventana ( new frame % [ label " Otros controles "]) )
;; Objetos de la ventana principal :
-------------------------------------------( define texto ( new message %
[ parent ventana ]
[ label " Objeto 'tab - panel % ':"]
153
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
))
( define opciones ( list " Botones " " Casillas de verificacin " " Opcin
mltiple " " Listas " " Cuadros de texto " " Otros " " Canvas ") )
( define tab ( new tab - panel %
[ parent ventana ]
[ choices opciones ]
[ callback
( lambda ( t c ) ; una instancia de 'tab - panel %' y de '
control - event %'
( let * ([ ix ( send tab get - selection ) ]
[ ix - str ( number - > string ix ) ]
[ nombre - ficha ( send tab get - item - label ix ) ])
( send mensaje set - label ( string - append " Se seleccion
la ficha " ix - str " con nombre '" nombre - ficha
" '") )
( send tab delete - child ( first ( send tab get - children )
))
( send tab add - child ( list - ref lista - pneles ix ) )
)
)]
))
( define mensaje ( new message %
[ parent ventana ]
[ label " Aqu se mostrarn los eventos de los objetos "]
[ auto - resize # t ]
))
33
34
35
;; Objetos pneles :
------------ ----------------------- ----------------------
154
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
( define
( define
( define
( define
( define
( define
( define
panel0
panel1
panel2
panel3
panel4
panel5
panel6
( new
( new
( new
( new
( new
( new
( new
vertical - panel %
vertical - panel %
vertical - panel %
vertical - panel %
vertical - panel %
vertical - panel %
vertical - panel %
[ parent
[ parent
[ parent
[ parent
[ parent
[ parent
[ parent
tab ]) )
tab ][ style
tab ][ style
tab ][ style
tab ][ style
tab ][ style
tab ][ style
'( deleted ) ]) )
'( deleted ) ]) )
'( deleted ) ]) )
'( deleted ) ]) )
'( deleted ) ]) )
'( deleted ) ]) )
( define lista - pneles ( list panel0 panel1 panel2 panel3 panel4 panel5
panel6 ) )
;; Panel 0 - Botones
---------- ----------------- ------------------ ------------( define panel - botones ( new horizontal - pane % [ parent panel0 ]) )
( define ( funcin - botn b c)
( send mensaje set - label ( string - append " Clic en el botn '" ( send b get label ) " '") )
)
( define botn1 ( new button %
[ parent panel - botones ]
[ label " aqu "]
[ callback funcin - botn ]) )
( define panel - botones2 ( new vertical - pane % [ parent panel - botones ]) )
( define botn2 ( new button %
[ parent panel - botones2 ]
[ label " all "]
[ callback funcin - botn ]) )
( define botn3 ( new button %
[ parent panel - botones2 ]
[ label " otro "]
155
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
156
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
157
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
158
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
))
;; Panel 3 - Listas ------------------------------------------------------( define ( funcin - lista r c) ; instancia de lista y ' control - event %'
( send mensaje set - label
( string - append " Se marc la opcin "
( number - > string ( send r get - selection ) )
" con texto '"
( send r get - string - selection )
" ' de la lista '"
( let ([ t ( send r get - label ) ])
( if t t " < sin - texto >") )
" '"
))
)
( define panel - lista1 ( new horizontal - pane % [ parent panel3 ]) )
( define eleccin1 ( new choice %
[ label " Primera lista "]
[ choices ( list " Opcin 1" " Opcin 2" " etc .") ]
[ parent panel - lista1 ]
[ callback funcin - lista ]
[ selection 2]
))
( define eleccin2 ( new choice %
[ label " Segunda lista "]
[ choices ( list " Opcin 1" " Opcin 2" " etc .") ]
[ parent panel - lista1 ]
[ callback funcin - lista ]
[ style ( list ' vertical - label )]
))
( define eleccin3 ( new choice %
[ label # f]
[ choices ( list " Opcin 1" " Opcin 2" " etc .") ]
[ parent panel - lista1 ]
[ callback funcin - lista ]
))
( define panel - lista2 ( new horizontal - pane % [ parent panel3 ]) )
( define lista1 ( new list - box %
[ label " Primera lista "]
[ choices ( list " Opcin 1" " Opcin 2" " etc .") ]
[ parent panel - lista2 ]
[ callback funcin - lista ]
[ selection 2]
))
( define lista2 ( new list - box %
[ label " Segunda lista "]
[ choices ( list " Opcin 1" " Opcin 2" " etc .") ]
[ parent panel - lista2 ]
[ callback funcin - lista ]
[ style ( list ' multiple ' vertical - label ) ]
))
159
160
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
[ choices null ]
[ callback
( lambda (c e )
( when ( equal ? ( send e get - event - type ) ' text - field enter )
( begin
( send c append ( send c get - value ) )
( send mensaje set - label
( string - append " Texto agregado : '"
( send c get - value )
" '") )
)
)
)]
))
;; Panel 5 - Otros ------------------------ -------------------------------( define msg - otros1 ( new message %
[ label " Slider :"]
[ parent panel5 ]) )
( define ( evento - slider s e )
( send mensaje set - label
( string - append " Valor del slider '"
( send s get - label )
" ': "
( number - > string ( send s get - value ) ) ) )
( if ( object =? s slider1 )
( send gauge1 set - value ( send s get - value ) )
( send gauge2 set - value ( send s get - value ) )
)
)
( define slider1 ( new slider %
[ label " Valor1 :"]
[ parent panel5 ]
[ min - value 0]
[ max - value 100]
[ init - value 30]
[ callback evento - slider ]
))
( define slider2 ( new slider %
[ label " Valor2 :"]
[ parent panel5 ]
[ min - value 0]
[ max - value 100]
[ style ( list ' vertical ' plain ) ]
[ callback evento - slider ]
))
( define msg - otros2 ( new message %
[ label " Gauge :"]
[ parent panel5 ]) )
161
162
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# lang racket
; canvas1 . rkt
( require racket / gui )
( define ventana ( new frame %
[ label " Ejemplo de dibujo en canvas "]
[ width 400]
[ height 400]) )
; Objeto ' canvas %'
( define canvas ( new canvas %
[ parent ventana ]
[ paint - callback ( lambda ( c dc ) ; instancia de ' canvas %'
y 'dc < %>'
( dibujar dc )
)]
163
))
; Colores :
( define negro ( make - object color % 0 0 0) ) ; RGB
( define rojo ( make - object color % 255 0 0) )
( define azul ( make - object color % 0 0 255) )
( define amarillo ( make - object color % 255 255 0) )
; Lpices y brochas
( define lpiz - negro - punteado ( make - object pen % negro 1 ' dot ) ) ; color grueso
estilo
( define lpiz - rojo - slido ( make - object pen % rojo 2 ' solid ) )
( define lpiz - azul - lneas ( make - object pen % azul 3 'long - dash ) )
( define lpiz - negro - invertido ( make - object pen % negro 1 ' xor ) )
( define lpiz - transparente ( make - object pen % negro 1 ' transparent ) )
( define brocha - negra - slida ( make - object brush % negro ' solid ) ) ; color
estilo
( define brocha - azul - invertida ( make - object brush % azul ' xor ) )
( define brocha - amarilla - rallada ( make - object brush % amarillo ' bdiagonal hatch ) )
( define brocha - transparente ( make - object brush % negro ' transparent ) )
; Funcin de dibujo
( define ( dibujar dc ) ; recibe una instancia del ' drawing context '
( send dc set - pen lpiz - negro - punteado )
( send dc set - brush brocha - amarilla - rallada )
( send dc draw - ellipse 50 50 200 200) ; x y ancho alto
( send dc set - pen lpiz - rojo - slido )
( send dc set - brush brocha - azul - invertida )
( send dc draw - rectangle 100 100 50 50) ; x y ancho alto
( send dc set - pen lpiz - azul - lneas )
( send dc draw - arc 100 100 50 50 0.0 pi ) ; x y ancho alto rad - inicio rad fin
( send dc set - brush brocha - transparente )
( send dc draw - arc 50 50 200 200 0.0 (/ pi 4) )
( send
( send
( send
( send
dc
dc
dc
dc
164
1
2
3
# lang racket
; canvas2 . rkt
( require racket / gui )
165
13
( super - new )
( define primer - punto ( make - object point % 0 0) )
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
1
2
3
# lang racket
; canvas3 . rkt
( require racket / gui )
4
5
6
7
166
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
[ width 400]
[ height 400]) )
;; Tcnica de doble buffer :
( define bitmap - de - buffer ( make - object bitmap % 400 400) )
( define dc ( make - object bitmap - dc % bitmap - de - buffer ) )
( send dc clear ) ; Esto inicializa el bitmap
( define canvas - hijo2 %
( class canvas %
( super - new )
( define primer - punto ( make - object point % 0 0) )
( define / override ( on - event evento )
( when ( send evento button - down ? ' left )
( send primer - punto set - x ( send evento get - x) )
( send primer - punto set - y ( send evento get - y) )
)
( when ( send evento button - up ? ' left )
( send dc draw - line
( send primer - punto get - x ) ( send primer - punto get - y )
( send evento get - x ) ( send evento get - y )
)
; Forzar el redibujado en este momento
( send this refresh )
167
))
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
)
( when ( and ( send evento dragging ?)
( send evento get - right - down ) )
( send dc draw - point ( send evento get - x ) ( send evento get - y ))
; Forzar el redibujado en este momento
( send this refresh )
)
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# lang racket
; canvas4 . rkt
( require racket / gui )
;; Tcnica de doble buffer :
( define bitmap - de - buffer ( make - object bitmap % 400 400) )
( define dc ( make - object bitmap - dc % bitmap - de - buffer ) )
( send dc clear ) ; Esto inicializa el bitmap
; Lpices :
( define negro ( make - object color % 0 0 0) )
( define lpiz - negro - slido
( make - object pen % negro 2 ' solid ) )
( define lpiz - negro - invertido ( make - object pen % negro 2 ' xor ) )
( send dc set - pen lpiz - negro - slido )
( define canvas - hijo2 %
( class canvas %
20
( super - new )
( define punto - ini - recta ( make - object point % 0 0) )
( define punto - ant - recta ( make - object point % 0 0) )
21
22
23
168
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
169
))
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
170
22 Mens
En la gura 22.1 se muestra el diagrama de clases de las clases relacionadas con mens en
Racket.
En la gura 22.2 se ilustra el diagrama de objetos de los mens implementados en el archivo
1-mens.rkt.
1
2
3
4
5
6
7
# lang racket
;1 - mens . rkt
( require racket / gui )
( define ventana ( new frame % [ label " Ejemplo de Mens "]) )
( define barra - menu ( new menu - bar % [ parent ventana ]
;[ demand - callback ( lambda ( bm ) ( printf " evento \ n ") )
]
171
22 Mens
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
))
( define txt - texto ( new text - field %
[ label # f]
[ parent ventana ]
[ style '( multiple ) ]
))
( send txt - texto min - width 600)
( send txt - texto min - height 600)
( define mnu - archivo ( new menu %
[ label "& Archivo "]
[ parent barra - menu ]) )
( define mnu - nuevo ( new menu - item %
[ parent mnu - archivo ]
[ label "& Nuevo "]
[ shortcut #\ n ]
[ callback ( lambda ( m c )
( send txt - texto set - value "")
)]
172
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
))
( define no - hacer - nada ( lambda ( m c ) ( void ) ))
( define mnu - abrir ( new menu - item %
[ parent mnu - archivo ]
[ label "& Abrir ..."]
[ shortcut #\ a ]
[ callback no - hacer - nada ]
))
( define mnu - guardar ( new menu - item %
[ parent mnu - archivo ]
[ label "& Guardar ..."]
[ shortcut #\ g ]
[ callback no - hacer - nada ]
))
( define mnu - sep ( new separator - menu - item % [ parent mnu - archivo ]) )
( define mnu - salir ( new menu - item %
[ parent mnu - archivo ]
[ label "& Salir "]
[ shortcut #\ s ]
[ callback ( lambda ( m c )
173
22 Mens
49
50
))
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
( define mnu - otro ( new menu % [ label " Otro men "][ parent barra - menu ]) )
( define mnu - submen ( new menu % [ label " Submen "][ parent mnu - otro ]) )
( define mnu - elemento1 ( new menu - item %
[ parent mnu - submen ]
[ label " Este es el primer subelemento "]
[ callback no - hacer - nada ]
))
( define mnu - elemento2 ( new menu - item %
[ parent mnu - submen ]
[ label " Este es el segundo subelemento "]
[ callback no - hacer - nada ]
))
( define mnu - seleccin ( new checkable - menu - item %
[ label " Chequame "]
[ parent mnu - otro ]
[ callback no - hacer - nada ]
))
( define mnu - mostrar - estado
( new menu - item %
[ label " Mostrar valor de ' Chequame '"]
[ parent mnu - otro ]
[ callback ( lambda ( m c )
( message - box " Ejemplo de ' message - box '"
( format " El valor del men ' Chequame ' es ~
a"
( send mnu - seleccin is - checked ?) ) )
)]
))
( send ventana show # t )
# lang racket
;3 - auxiliar . rkt
( require racket / gui )
( provide abrir - archivo guardar - archivo )
( define ( abrir - archivo msg par )
( define ruta ( get - file msg par # f # f " txt " null '( (" Archivos de texto "
"*. txt ") (" Todos " "*.*") ) ) )
( if ruta
( path - > string ruta )
#f
174
1
2
3
4
5
6
7
8
9
10
# lang racket
;2 - mens . rkt
( require racket / gui )
( require "3 - auxiliar . rkt ")
( define ventana ( new frame % [ label " Ejemplo de Mens y dilogos bsicos "]) )
( define barra - menu ( new menu - bar % [ parent ventana ]
))
( define txt - texto ( new text - field %
[ label # f]
175
22 Mens
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
[ parent ventana ]
[ style '( multiple ) ]
))
( send txt - texto min - width 600)
( send txt - texto min - height 600)
( define mnu - archivo ( new menu %
[ label "& Archivo "]
[ parent barra - menu ]) )
( define mnu - nuevo ( new menu - item %
[ parent mnu - archivo ]
[ label "& Nuevo "]
[ shortcut #\ n ]
[ callback ( lambda ( m c )
( send txt - texto set - value "")
)]
))
( define no - hacer - nada ( lambda ( m c ) ( void ) ))
( define mnu - abrir ( new menu - item %
[ parent mnu - archivo ]
[ label "& Abrir ..."]
[ shortcut #\ a ]
[ callback
( lambda ( m c )
( let ([ nombre - archivo ( abrir - archivo " Abrir
archivo ..." ventana ) ])
( when nombre - archivo
( call - with - input - file nombre - archivo
( lambda ( f)
( define ( aux f )
( let ([ cadena ( read - string 1000 f ) ])
( unless ( eof - object ? cadena )
( send txt - texto set - value
( string - append ( send txt texto get - value )
cadena )
)
)
)
)
( send txt - texto set - value "")
( aux f )
)
)
)
)
)]
))
( define mnu - guardar ( new menu - item %
[ parent mnu - archivo ]
176
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
( define mnu - sep ( new separator - menu - item % [ parent mnu - archivo ]) )
( define mnu - salir ( new menu - item %
[ parent mnu - archivo ]
[ label "& Salir "]
[ shortcut #\ s ]
[ callback ( lambda ( m c )
( send ventana show # f )
)]
))
86
87
88
# lang racket
;4 - mens - contextuales . rkt
( require racket / gui )
( define ventana ( new frame % [ label " Ejemplo de Mens Contextuales "]) )
( define brocha ( make - object brush % ( make - object color % 0 0 255) ' solid ) )
( define mi - canvas %
( class canvas %
( super - new )
( define / override ( on - event evento )
; BOTN DERECHO
( when ( send evento button - down ? ' right )
( send this popup - menu men ( send evento get - x ) ( send evento get - y ) )
177
22 Mens
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
))
( define canvas ( new mi - canvas %
[ parent ventana ]
[ paint - callback
( lambda (c dc )
( define - values ( ancho alto ) ( send dc get - size ) )
( send dc set - brush brocha )
( send dc draw - rectangle 0 0 ancho alto )
)]
))
( send ventana min - width 600)
( send ventana min - height 600)
( define ( imprime - men m c )
( printf " Opcin seleccionada : '~a '\ n " ( send m get - label ) )
)
( define men ( new popup - menu % ) )
( define opcin1 ( new menu - item %
[ parent men ]
[ label " Opcin 1"]
[ callback imprime - men ]
))
( define opcin2 ( new menu - item %
[ parent men ]
[ label " Opcin 2"]
[ callback imprime - men ]
))
( define opcin3 ( new menu - item %
[ parent men ]
[ label " Opcin 3"]
[ callback imprime - men ]
))
52
53
54
1
2
3
4
5
6
7
8
# lang racket
;5 - seleccin - color . rkt
( require racket / gui )
;; Tcnica de doble buffer :
( define bitmap - de - buffer ( make - object bitmap % 400 400) )
( define dc ( make - object bitmap - dc % bitmap - de - buffer ) )
178
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
37
38
39
179
22 Mens
40
41
42
43
44
45
))
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
)
( send punto - ant - lpiz set - x ( send evento get - x ) )
( send punto - ant - lpiz set - y ( send evento get - y ) )
( send this refresh )
)
66
67
68
180
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
181
22 Mens
( send dc set - pen lpiz - slido )
)]
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
))
( define opcin3 ( new menu - item %
[ parent men ]
[ label " Azul "]
[ callback
( lambda ( m c )
( send dc set - pen lpiz - invertido )
( send lpiz - slido set - color ( make - object color % 0
0 255) )
( send dc set - pen lpiz - slido )
)]
))
( define opcin4 ( new menu - item %
[ parent men ]
[ label " Otro ..."]
[ callback
( lambda ( m c )
( send dc set - pen lpiz - invertido )
;( send lpiz - slido set - color ( make - object color % 0
0 255) )
( let ([ nuevo - color ( get - color - from - user " Elija un
color " ventana ( send lpiz - slido get - color ) ) ])
( when nuevo - color
( send lpiz - slido set - color nuevo - color )
)
)
( send dc set - pen lpiz - slido )
)]
))
( send ventana show # t )
182
23 Proyecto: Minipaint
1
2
3
4
5
6
# lang racket
; mini - paint . rkt
( require racket / gui )
( define ANCHO 600)
183
23 Proyecto: Minipaint
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
( super - new )
( define punto - inicial ( make - object point % 0 0) ) ; Punto sobre el que hizo
clic al principio .
( define punto - anterior ( make - object point % 0 0) ) ; Punto anterior donde
estuvo el ratn .
( define rect - x 0)
( define rect - y 0)
( define rect - ancho 0)
( define rect - alto 0)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
184
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
185
23 Proyecto: Minipaint
( send dc draw - line
( send punto - inicial get - x ) ( send punto - inicial get - y )
( send evento get - x ) ( send evento get - y )
)
; Forzar el redibujado en este momento
( send this refresh )
)
107
108
109
110
111
112
113
)
;; Rectngulo :
( when ( equal ? forma ' rectngulo )
( when ( send evento button - down ? ' left )
( send punto - inicial set - x ( send evento get -x ) )
( send punto - inicial set - y ( send evento get -y ) )
( send punto - anterior set - x ( send evento get - x ) )
( send punto - anterior set - y ( send evento get - y ) )
( set ! rect - x ( send evento get - x ) )
( set ! rect - y ( send evento get - x ) )
( set ! rect - ancho 0)
( set ! rect - alto 0)
( send dc set - pen lpiz - invertido )
( set ! modificado ? # t )
)
( when ( and ( send evento dragging ?)
( send evento get - left - down ) )
( send dc draw - rectangle rect - x rect - y rect - ancho rect - alto )
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
))
155
156
157
186
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
( class frame %
( super - new )
( define / augment ( on - close )
( send mnu - salir command ( new control - event % [ event - type ' menu ]) )
)
))
( define ventana ( new frame - hijo %
[ label " Mini - paint "]
[ stretchable - width # f ]
[ stretchable - height # f ]
))
( define mi - canvas ( new canvas - hijo %
[ parent ventana ]
[ min - width ANCHO ]
[ min - height ALTO ]
[ style '(no - focus ) ]
[ paint - callback
( lambda ( c dc - canvas )
; Dibuja el bitmap en el dc - canvas :
( send dc - canvas draw - bitmap bitmap - de - buffer 0 0)
)]
))
( define panel ( new horizontal - panel % [ parent ventana ]) )
( define radio - forma ( new radio - box %
[ label " Seleccione forma de dibujo :"]
[ parent panel ]
[ choices ( list " Forma libre " " Lnea " " Rectngulo ")
]
[ callback
( lambda ( r c )
( set ! forma ( list - ref lista -de - formas ( send r
get - selection ) ) )
)]
[ style ( list ' vertical ' vertical - label ) ]
))
( define radio - color ( new radio - box %
[ label " Seleccione el color :"]
[ parent panel ]
[ choices ( list " Negro " " Blanco " " Rojo " " Verde " "
Azul " " Otro ...") ]
[ callback
( lambda ( r c )
( send dc set - pen lpiz - invertido )
( send lpiz - slido set - color
( case ( send r get - selection )
[(0) ( make - object color % 0 0 0) ]
[(1) ( make - object color % 255 255 255) ]
[(2) ( make - object color % 255 0 0) ]
[(3) ( make - object color % 0 255 0) ]
187
23 Proyecto: Minipaint
[(4) ( make - object color % 0 0 255) ]
[(5)
( let ([ nuevo - color
( get - color - from - user " Elija un
color " ventana ( send lpiz slido get - color ) ) ])
( if nuevo - color nuevo - color ( send
lpiz - slido get - color ) )
)
]
)
206
207
208
209
210
211
212
213
)
( send dc set - pen lpiz - slido )
( send lpiz - invertido set - color ( send lpiz slido get - color ) )
)]
[ style ( list ' vertical ' vertical - label ) ]
))
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
188
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
189
23 Proyecto: Minipaint
293
294
295
296
297
298
299
300
301
))
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
)]
190
( lambda ( m c )
( when ( and modificado ?
( equal ? 1
( message - box / custom
" Advertencia "
" No ha guardado el archivo
actual "
" Guardar archivo "
" No guardar "
#f
ventana
'( caution disallow - close
default =1)
)))
( if nombre - del - archivo
( send bitmap - de - buffer save - file nombre - del
- archivo ' png )
( let ([ nombre - archivo ( guardar - archivo "
Guardar archivo ..." ventana ) ])
( if nombre - archivo
( send bitmap - de - buffer save - file
nombre - archivo ' png )
( void )
)
)
)
)
( send ventana show # f )
)]
))
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
191
23 Proyecto: Minipaint
192
193
23 Proyecto: Minipaint
inicialmente tendr un rea de texto vaca donde se pueda escribir, al presionar el
men archivo y la opcin de nuevo, el contenido del rea de texto se borrar, dejando
limpia el rea de texto, si se presiona la opcin abrir, se abrir un cuadro de dialogo
para poder buscar y seleccionar una archivo de texto, luego al seleccionar y abrir
el archivo seleccionado, la informacin se cargar en el rea de texto, para poder
editarse, si se desea o si slo se desea ver el contenido. Si se elige la opcin de guardar
se abrir un cuadro de dialogo para poder guardar el archivo en un lugar del disco
duro, donde se desee. Y al presionar la opcin de salir, el programa terminar.
6. Elaborar un programa que muestre una ventana que contenga un list-box de 5 elementos (elementos de su eleccin) y un botn seleccionar , cuando se d clic a dicho
botn, deber aparecer una ventana emergente con el elemento seleccionado al centro
de la ventana y un botn salir que permitir cerrar la ventana emergente.
7. Realizar un programa que muestre una ventana cuyo ttulo ser "formulario" en esta
se presentar un formulario donde el usuario ingresar los siguientes datos:
a)
b)
c)
d)
- Nombre (text-eld)
- edad (combo-box edad mxima 90 aos)
- sexo (radio-button M F)
- botn nalizar
El botn nalizar cerrar la ventana "formulario" y abrir la ventana "revisado"
donde mostrar los datos ingresados por el usuario, esta ventana presentar dos
botones "guardar" y "salir".
"guardar": Los datos sern guardados en un archivo.
"salir": cerrar el programa en caso de no guardar enviar un mensaje que indique
"datos no almacenados".
8. Realizar un programa que muestre la ventana cuyo ttulo ser "pases" esta presentar
un list-box que contendr una lista de pases almacenados en el archivo "pases.txt"
y presentar dos botones "eliminar" "salir".
"eliminar": eliminar el pas seleccionado de la lista y del archivo.
"salir" : cerrar la ventana.
9. Realizar un programa que muestre una ventana cuyo ttulo ser "Seleccionar ao",
esta ventana presentar un slider que tendr una lista de aos desde el ao 1900 hasta
el ao 3000 y un botn "seleccionar", al dar clic al botn "seleccionar" aparecer una
ventana cuyo ttulo ser el ao seleccionado, esta ventana contendr dos text-eld
"nombre" y "suceso" en donde se almacenar el nombre de la persona que digita la
informacin y el suceso ocurrido en el ao seleccionado nalmente la ventana presentar el botn "guardar" lo cual permitir almacenar la informacin en un archivo.
Nota la ventana "seleccionar ao" no debe cerrarse sino simplemente quedar inactiva
mientras se ingresan los datos en la segunda ventana, al momento de guardar la in-
194
195
23 Proyecto: Minipaint
196
Parte V
Apndices
197
Racket
es el nuevo nombre de
PLT Scheme,
.rkt.
.ss
.scm.
scheme
y no
racket
como en Racket. Por ello, la primera lnea de los programas de PLT Scheme deben
comenzar con la lnea:
#lang scheme,
en lugar de
#lang racket
drracket.
como en Racket.
drscheme
(y se llama
mzscheme
en lugar de
racket.
mred
en lugar de
gracket.
mzc
en lugar de
raco:
scheme/gui.
199
200
Bibliografa
[1] http://docs.racket-lang.org/ (2009-2010) -
Computing and Programming), por Matthias Felleisen, Robert Bruce Findler, Matthew
Flatt, Shriram Krishnamurthi. The MIT Press, Massachusetts Institute of Technology.
201