CAPÍTULO IV: Programación Funcional - inf.utfsm.clnoell/PLP-UCV/apunte04.pdf · caracteres;...

84
1 CAPÍTULO IV: Programación Funcional Prof. Teddy Alfaro 4.1 Introducción a la Programación Funcional

Transcript of CAPÍTULO IV: Programación Funcional - inf.utfsm.clnoell/PLP-UCV/apunte04.pdf · caracteres;...

1

CAPÍTULO IV:Programación Funcional

Prof. Teddy Alfaro

4.1 Introducción a la Programación Funcional

2

Programación Funcional

• Paradigma diferente a los imperativos, que se aleja de la máquina de von Neumann

• Basado en funciones matemática (notación funcional lambda de Church)

• No existen realmente arquitecturas de computadores que permitan la eficiente ejecución de programas funcionales

• LISP es el primero, del cual derivan Scheme, Common LISP, ML y Haskell

Funciones Matemáticas

• Un función es una proyección de un conjunto dominio a uno que es el rango

• La evaluación de funciones está controlada por recursión y condiciones (imperativos lo hacen normalmente por secuencias e iteraciones)

• Funciones matemáticas entregan siempre el mismo valor para el mismo conjunto de argumentos y, por lo tanto, no tiene efectos laterales.

f: D → R

3

Formas Funcionales(funciones de orden superior)

Toman funciones como parámetros y/o producen funciones como resultado

�Composición de Funcionesh ≡ f ° g entonces: h(x) ≡ f(g(x))

�Construcción. Lista se funciones que se aplican[f, g](x) produce (f(x), g(x))

�Aplicar a todo. Una función se aplica a lista arg.α (f, (x, y, z)) produce (f(x), f(y), f(z))

Fundamentos de la PF

• La PF pura no usa variables ni asignación• Repetición debe ser lograda con recursión• Un programa consiste de definición de

funciones y aplicación de éstas• La ejecución del programa no es nada más que

la evaluación de funciones• La transparencia referencial se refiere a que la

evaluación de una función simpre produce el mismo resultado

4

Lenguajes Funcionales

• El lenguaje provee algunas funciones básicas, que son primitivas para construir funciones más complejas.

• Se definen algunas estructuras para representar datos en los parámetros y resultados de las funciones.

• Normalmente se implementan mediante interpretadores, pero también se pueden compilar.

4.2 Introducción al Lenguaje Scheme

Sintaxis, listas, operadores básicos, expresiones lambda y

definición de variables

5

Origen de Scheme

• Desarrollado en el MIT a mediados del ´70• Es un dialecto de LISP• Usado para enseñanza de programación• Características:

– Pequeño con sintaxis y semántica simple– Nombres tienen ámbito estático– Funciones son entitades de primera clase, y

por lo tanto se tratan como cualquier valor

Sintaxis

• Palabras claves• Variables• Datos constantes (e.g. números;

caracteres; strings; vectores, listas y símbolos citados)

• Formas estructuradas• Blancos y comentarios (después de ;)

6

Identificadores

• Corresponden a palabras claves, variables ysímbolos, que no son sensible a mayúsculas

• Se forman de:– mayúsculas y minúsculas [´A´ .. ´Z´, ´a´..´z´]– Dígitos [´0´..´9´]– Caracteres [? ! . + - * / < = > : $ % ^ & _ ˜ ]

• Identificadores no pueden comenzar con ningún carácter que comienza un número (i.e. dígito, +, - y .), excepto casos de identificadores como + y ...

Ejemplo de Identificadores

• X3 y ?$!!! Son válidos• Abcd y AbcD Son el mismo• 8id no es válido

7

Constantes Básicas

• String: se escribe usan citado doble (“)– e.g. “Un string es sensible a Mayusculas”

• Un caracter precede de #\– e.g. #\a

• Un número pueden ser enteros, fraccionarios, punto flotante y en notación científica– e.g. -365, 1/4, 23.46, 1.3e27

• Números complejos en coordenadas rectangulares y polares– e.g. 2.7-4.5i [email protected]

• Booleanos son los valores #f (falso) y #t (verdadero)

Ambiente Interactivo de Scheme

• Corresponde al ciclo: leer, evaluar e imprimir(denominado REPL).

• El sistema entrega un pronto, se ingresa la expresión, el sistema evalúa y entrega el resultado.

Ejemplo:“Hola Scheme” => “Hola Scheme”(Toda constante evalúa en la misma constante)

• Es posible cargar y salvar en un archivo para facilitar el proceso de desarrollo.

8

Listas

• Las listas se escriben con paréntesis redondos(a b c d)

• Listas contienen elementos de cualquier tipo, y se pueden anidar

(lambda (x) (* n n))• Una función se escribe como una lista en

notación prefija, correspondiendo el primer elemento de la lista a la función y los siguientes a los argumentos

(+ 3 14) ;=> 17

Funciones Aritméticas

• Los nombres +, -, * y / son nombres reservados para las operaciones aritméticas.

• Funciones se escriben como listas en notación prefija:(+ 1/2 1/2) ;=> 1(- 2 (* 4 1/3)) ;=> 2/3(/ (* 6/7 7/2) (- 4.5 1.5)) ;=> 1.0

9

Evaluación de Listas

• Toda lista es evaluada, salvo que se especifique lo contrario con citación simple (quote)

(quote (a b c d)) ;=> (a b c d)‘(a b c d) ;=> (a b c d)(a b c d) ;=> ERROR (“a” no es proc.)

• Al no usar quote, Scheme trata de evaluar considerando en el ejemplo a a como variable de función.

Operadores Básicos de Listas

• car devuelve el primer elemento de la lista:(car ‘(a b c d)) ;=> a

• cdr devuelve el resto de la lista (sin el primer elemento):

(cdr ‘(a b c d)) ;=> (b c d)

10

Estructura de una Lista

(A (B C) D)

A

B D

C

Constructores de Listas

• cons construye una nueva lista cuyo car y cdrson los dos argumentos:(cons ´a ´(b c d)) ;=> (a b c d)(cons (car ´(a b c))(cdr ´(a b c));=> (a b c)(cons ´a ´b) ;=> ?

• list construye una lista con todos los argumentos(list ´a ´b ´c ´d) ;=> (a b c d)(list) ;=> ()

11

Listas Impropias

A

BD

C

E

(A (B C) D . E) ≡ (A . ( (B . (C . ()) . (D . E)))

Variables y Expresiones Let

• Let permite definir variable que se ligan a un valor en la evaluación de expresiones

• Sintaxis:(let ((var1 val1) … ) exp1 exp2 … )

• Ejemplo:

(let ((x 2) (y 3))(* (+ x y) (- x y)) )

=> -5

¡Variables sonsólo visiblesdentro del cuerpode LET!

12

Expresiones Lambda

• Permite crear un nuevo procedimiento• Sintaxis:

(lambda (var1 var2 … ) exp1 exp2 … )• Ejemplo:

((lambda (x) (* x x)) 3);=> 9

¡Una expresión lambda es una objeto tipo procedimientoque no tiene nombre!

Ejemplo: Expresión Lambda

(let ((square (lambda (x) (* x x))))(list (square 2)

(square 3)(square 4)

))

;=> (4 9 16)

13

Relación entre Let y Lambda

Nótese que:

(let ((var1 val1) … (varm valm)) exp1 … expn)

equivale a:

((lambda (var1 … varm) exp1 … expn) val1 … valm)

Especificación de Parámetros Formales

•Lista propia de parámetros (var1 var2 ... varn)

((lambda (x y) (list x y)) 1 2) ;=> (1 2)

•Lista impropia de parámetros (var1 var2 ... varn . varr)

((lambda (x . y) (list x y)) 1 2 3) ;=> (1 (2 3))

•Parámetros único varr

((lambda x (list x)) 1 2) ;=> ((1 2))

14

Definiciones de Nivel Superior

• Las variables definidas con let y lambda son sólo visibles en el cuerpo de las expresiones (local).

• El procedimiento define permite definir variables de nivel superior (global)

• Definiciones de nivel superior permiten visibilidad en cada expresión donde no sean escondidas por otro ligado (e.g. Una variable definida con el mismo nombre mediante letoculta a la de nivel superior)

Ejemplo de uso de Define

(define pi 3.1416);=> pi

(define square (lambda (x) (* x x))));=> square

(square 3);=> 9

(let ((x 2)(square 4)) (* x square));=> 8

15

Abreviación en Definición de Funciones

• La forma:(define var0 (lambda (var1 … varn) e1 …))

• Se puede abreviar como:(define (var0 var1 … varn) e1 …)

• Ejemplo:

(define square (lambda (x) (* x x))))equivale a:

(define (square x) (* x x))

Expresiones Condicionales

• En Scheme también es posible condicionar la realización de determinada tarea

• Sintaxis:(if test consecuencia alternativa)

• Ejemplo:(define (abs n) (if (> n 0)

n(- 0 n)))

(abs -27) ;=> 27

16

Predicados

• Procedimientos para expresiones relacionales

=, <, >, <= y >=

• Procedimientos para expresiones lógicosor, and y not

e.g. (= 3 4) => #f

e.g. (and (> 5 2) (< 5 10)) => #t

Otros Predicados

• Lista nula: null?(null? ´()) => #t

• Argumentos equivalentes: eqv?(eqv? ´a ´a) => #t

• Ejemplo:

(define (reciproco x) (if (and (number? n) (not (= n 0))

(/ 1 n)(error ‘reciproco“reciproco: división no válida”)

))

17

Expresión Condicional Múltiple

• Scheme provee expresiones que se evalúan condicionalmente.

• Sintaxis:(cond (test1 exp1) (test2 exp2) … (else expn)

• El uso de else es opcional, siendo equivalente su uso a colocar #t

Ejemplo de Condicional Múltiple

(define abs(lambda (x)

(cond ((= x 0) 0) ((< x 0) (- 0 x))(else x)

))

)

18

Un ejemplo más complicado(define nota

(lambda (cert lect tar)(let ((a ((lambda (c)

(cond((< c 45) 0)((> c 60) 0.3)(else (/ (* 0.3 (- c 45)) 15))

)) cert)

)) (display "alfa: ") (display a) (newline)(+ (* a tar)(* (- 1 a) (+(* 0.75 cert) (* 0.25 lect))))

))

)

(nota 52.5 60 100)alfa: .15;=> 61.21875

Algo más sobre Predicados

• Cualquier objeto se interpreta como #t• La lista nula ‘() equivale a #f• Se definen los predicados:

pair? : verifica si es un par (lista propia o impropia)

number? : verifica si es númerostring? : verifica si es un string

19

4.3 Recursión en Scheme

Recursión simple y asignación

Recursión Simple

• Un procedimiento recursivo es aquel se aplica a si mismo.

• Ejemplo:

(define length(lambda (ls)

(if (null? ls)0(+ 1 (length (cdr ls))))))

; => length

(length '(a b c d)) ; => 4

20

Ejemplo1: Procedimiento memv

;; El siguiente procedimiento busca x en la lista ls,;; devuelve el resto de la lista después de x ó ()

(define memv (lambda (x ls)(cond

((null? ls) ())((eqv? x (car ls)) (cdr ls))(else (memv x (cdr ls)))

))

)

; => memv

(memv 'c '(a b c d e)) ; => (d e)

Ejemplo2: Procedimiento remv

;; Devuelve la lista equivalente a ls eliminando ;; toda ocurrencia de x

(define remv(lambda (x ls)

(cond((null? ls) ())((eqv? x (car ls)) (remv x (cdr ls)))(else (cons (car ls) (remv x (cdr ls))))

))

); =>remv

(remv 'c '(a b c d e c r e d )) ;=> (a b d e r e d )

21

Ejemplo: Copiar Árbol

;;; tree-copy: copia en forma recursiva el arbol tr

(define tree-copy(lambda (tr)

(if (not(pair? tr)) tr(cons (tree-copy (car tr))

(tree-copy (cdr tr))))

)); =>tree-copy

(tree-copy '(a (b c) d (d (e f(h))))); =>(a (b c) d (d (e f (h))))

Ejemplo de Recursión (1/3)

;;; abs-all: genera una lista con los valores ;;; absolutos de la lista ls

(define abs-all(lambda (ls)

(if (null? ls)()(cons (abs (car ls)) (abs-all (cdr ls)))

))

); => abs-all

(abs-all '(3 7 -10 5 -8)) ; => (3 7 10 5 8)

22

Ejemplo de Recursión (2/3)

;;; abs-all1: genera una lista con los valores ;;; absolutos de la lista ls, usando el procedimiento map

(define abs-all1(lambda (ls) (map abs ls))

)

; => abs-all1

(abs-all1 '(3 7 -10 5 -8)) ; => (3 7 10 5 8)

;;; que se puede expresar directamente como:

(map abs '(3 7 -10 5 -8)) ; => (3 7 10 5 8)

Ejemplo de Recursión (3/3)

;;; map1: implementa la funcion map

(define map1(lambda (proc ls)

(if (null? ls)()(cons (proc (car ls)) (map1 proc (cdr ls)))

))

); =>map1

(map1 abs '(3 7 -10 5 8)) ; => (3 7 10 5 8)

23

Asignación

• let permite ligar un valor a una (nueva) variable en su cuerpo (local), como define permite ligar un valor a una (nueva) variable de nivel superior.

• Sin embargo, let y define no permiten cambiar el ligado de una variable ya existente, como lo haría una asignación.

• set! Permite en Scheme re-ligar a una variable existente un nuevo valor, como lo haría una asignación.

Ejemplo: Asignación

(define abcde '(a b c d e)); => abcde

abcde; => (a b c d e)

(set! abcde (cdr abcde)); => (a b c d e)

abcde; => (b c d e)

24

Ejemplo: Ecuación Cuadrada (1/2)

(define raices-cuadradas(lambda (a b c)

(let ((menosb 0) (raiz 0) (divisor 1) (raiz1 0) (raiz2 0))

(set! menosb (- 0 b))(set! divisor (* 2 a))(set! raiz (sqrt (- (* b b) (* 4 (* a c)))))(set! raiz1 (/ (+ menosb raiz) divisor))(set! raiz2 (/ (- menosb raiz) divisor))

(cons raiz1 raiz2))

)); => raices-cuadradas

Ejemplo: Ecuación Cuadrada (2/2)

(define raices-cuadradas1(lambda (a b c)

(let ( (menosb (- 0 b))(raiz (sqrt (- (* b b) (* 4 (* a c)))))(divisor (* 2 a)))(let ((raiz1 (/ (+ menosb raiz) divisor))

(raiz2 (/ (- menosb raiz) divisor)))(cons raiz1 raiz2)))))

; => raices-cuadradas1

(raices-cuadradas 2 -4 -30) ; => (5 . -3)

(raices-cuadradas1 2 -4 -30) ; => (5 . -3)

25

Ejemplo: Contador(1/3)

;;; definicion de un contador usando variable de ;;; nivel superior

(define contador 0); => contador

(define cuenta(lambda ()

(set! contador (+ contador 1))contador

)); => cuenta

(cuenta) ; => 1(cuenta) ; => 2

Ejemplo: Contador(2/3)

;;; la siguiente solucion usando let define una variable;;; que no es visible fuera de su definicion

(define cuenta1(let ((cont 0))

(lambda ()(set! cont (+ cont 1))cont

))

); => cuenta1

(cuenta1) ; => 1

(cuenta1) ; => 2

26

Ejemplo: Contador(3/3)(define hacer-contador

(lambda ()(let ((cont 0))

(lambda ()(set! cont (+ cont 1))cont

))

)); => hacer-contador

(define cont1 (hacer-contador)) ; => cont1(define cont2 (hacer-contador)) ; => cont2(cont1) ; => 1(cont2) ; => 1(cont1) ; => 2(cont1) ; => 3(cont2) ; => 2

Ejemplo: Evaluación Perezosa (1/2)

;;; lazy: evaluacion perezosa de la expresion t, la cual ;;; es solo evaluada la primera vez que se invoca.

(define lazy(lambda (t)

(let ((val #f) (flag #f))(lambda ()

(if (not flag)(begin (set! val (t))(set! flag #t))

)val

))

)); => lazy

27

Ejemplo: Evaluación Perezosa (2/2)

(define imprime(lazy (lambda ()

(display "Primera vez!")(newline)"imprime: me llamaron"

))

); => imprime

(imprime)Primera vez!; => "imprime: me llamaron"

(imprime); => "imprime: me llamaron"

Ejemplo: Stack (1/2)

;;; haga-stack: es un procedimiento que permite crear un stack;;; que tiene las operaciones: vacio? , push! , pop! y tope!

(define haga-stack(lambda ()(let ((st '()))(lambda (op . args)

(cond((eqv? op 'vacio?)(null? st))((eqv? op 'push!) (begin (set! st (cons (car args) st))) st)((eqv? op 'pop!) (begin (set! st (cdr st))) st)((eqv? op 'tope!) (car st))(else "operacion no valida")

))

))

); => haga-stack

28

Ejemplo: Stack (2/2)

(define st (haga-stack)) ; => st

(st 'vacio?) ; => #t

(st 'push! 'perro) ; => (perro)

(st 'push! 'gato) ; => (gato perro)

(st 'push! 'canario) ; => (canario gato perro)

(st 'tope!) ; => canario

(st 'vacio?) ; => ()

(st 'pop!) ; => (gato perro)

4.4 Aspectos más Avanzados sobre Scheme

Otras formas de definición de variables y recursión de cola

29

Formas let para definición de variables

• Procedimientos recursivos se han definido con variables de nivel superior

• Hasta ahora se ha visto una forma let para definir variables locales, sólo visibles en el cuerpo

• Ejemplo:(let ((suma (lambda (ls)

(if (null? ls)0(+ (car ls) (suma (cdr ls))))

)))(suma '(1 2 3 4 5 6))

)¡No es visible!

Recursión con let

;;; se puede solucionar el problema entregando ;;; suma como argumento a la expresion lambda,;;; siendo la solución más complicada

(let ((suma (lambda (suma ls)(if (null? ls)

0(+ (car ls) (suma suma (cdr ls)))

))

))(suma suma '(1 2 3 4 5 6))

);=> 21

30

Aplicación de letrec

;;; letrec hace visible las variables dentro ;;; de los valores definido, permitiendo ;;; definiciones recursivas con ámbito local

(letrec ((suma (lambda (ls)(if (null? ls)

0(+ (car ls) (suma (cdr ls)))

))

))(suma '(1 2 3 4 5 6))

)

Ejemplo de Recursión Mutua

(letrec((par?

(lambda (x)(or (= x 0) (impar? (- x 1)))

))(impar?(lambda (x)

(and (not (= x 0)) (par? (- x 1)) ))

))

(list (par? 20) (impar? 20)));=> (#t ())

31

Definición letrec• Definiciones son también visibles en los

valores de las variables• Se usa principalmente para definir

expresiones lambda• Existe la restricción que cada valor debe

ser evaluable sin necesidad de evaluar otros valores definidos (expresiones lambda lo cumplen)

Ejemplo de letrec

(letrec ((f (lambda () (+ x 2)))(x 1))

(f));=> 3

(letrec ((y (+ x 2))(x 1))

y);=> error

¡Es válido!

¡No es válido!

32

Definición let con nombre

( (lambda (ls)(let suma ((l ls))

(if (null? l)0(+ (car l) (suma (cdr l)))

))

)'(1 2 3 4 5 6)

)

;=> 21

Equivalencia entre letrec ylet con nombre

• La expresión let con nombre:(let nombre ((var val) ...) exp1 exp2 ...)

• equivale a la expresión letrec:((letrec ((nombre

(lambda (var ...) exp1 exp2 ...)))

nombre ;; fin de cuerpo de letrec)val ...)

33

Recursión de Cola

• Cuando un llamado a procedimiento aparece al final de una expresión lambda, es un llamado de cola (no debe quedar nada por evaluar de la expresión lambda, excepto retornar el valor del llamado)

• Recursión de cola es cuando un procedimiento hace un llamado de cola hacia si mismo, óindirectamente a través de una serie de llamados de cola hacia si mismo.

Ejemplo: Llamado de Cola

• Lo son los llamados a f:

• No lo son respecto a g:

(lambda () (if (g) (f) #f))(lambda () (or (g) (f)))

(lambda () (if (g) (f) #f))(lambda () (or (g) (f)))

34

Propiedad de la Recursión de Cola

• Scheme trata las llamadas de cola como un goto o salto de control (jump).

• Por lo tanto, se pueden hacer un número indefinido de llamados de cola sin causar overflow del stack.

• Es recomendable transformar algoritmos que producen mucho anidamiento en la recursión a uno que sólo use recursión de cola.

Ejemplo1: Factorial (1/2)(sin recursión de cola)

(define factorial(lambda (n)

(let fact ((i n))(if (= i 0)

1(* i (fact (- i 1)))

))

)); => factorial

(factorial 5) ; => 120

n! = n * (n-1)!0! = 1

35

Ejemplo1: Factorial (2/2)(con recursión de cola)

(define factorial1(lambda (n)

(let fact ((i n) (a 1))(if (= i 0)

a(fact (- i 1) (* a i))

))

)); => factorial1

(factorial1 5) ; => 120

n! = n * (n-1) * (n-2) * ... 2 * 1

Ejemplo2: Fibonacci (1/2)(sin recursión de cola)

(define fibonacci(lambda (n)

(let fib ((i n))(cond

((= i 0) 0)((= i 1) 1)(else (+ (fib (- i 1)) (fib (- i 2))))

))

)); => fibonacci

(fibonacci 20) ; => 6765

fib(n) = fib(n-1) + fib(n-2)fib(0) = 0 y fib(1) = 1

36

Ejemplo2: Fibonacci (2/2)(con recursión de cola)

(define fibonacci1(lambda (n)(if (= n 0)

0(let fib ((i n) (a1 1) (a0 0))

(if (= i 1)a1(fib (- i 1) (+ a1 a0) a1)

))

))

); => fibonacci1

(fibonacci1 20) ; => 6765

Ejemplo de Factorización

(define factorizar(lambda (n)

(let fact ((n n) (i 2))(cond

((>= i n) '())((integer? (/ n i)) (cons i (fact (/ n i) i)))(else (fact n (+ i 1)))

))));=> factorizar

(factorizar 120) ;=> (2 2 2 3 5)(factorizar 37897) ;=> (37897)(factorizar 1) ;=> ()

Recursiva de cola

No recursiva de cola

37

Continuaciones

• Evaluación de expresiones Schemeimplica dos decisiones:– ¿Qué evaluar?– ¿Qué hacer con el valor de la evaluación?

• Se denomina continuación al punto de la evaluación donde se tiene un valor y se está listo para seguir o terminar.

Procedimientocall-with-current-continuation

• Procedimiento que se puede abreviar como call/cc

• call/cc se pasa como argumento formal a un procedimiento p

• call/cc obtiene la continuación actual y se lo pasa como argumento actual a p.

38

Procedimientocall-with-current-continuation

• La continuación se representa por k, donde cada vez que se aplica a un valor, éste retorna este valor a la continuación de la aplicación de call/cc.

• Este valor se convierte en el valor de la aplicación de call/cc.

• Si p retorna sin invocar k, el valor retornado por p es el valor de la aplicación de call/cc.

Ejemplo de Continuación

(define call/cc call-with-current-continuation);=> Value: call/cc

(call/cc (lambda (k) (* 4 5)));=> Value: 20

(call/cc (lambda (k) (* 5 (+ 2 (k 7)))));=> Value: 7

39

Ejemplo 1: call/cc

(define producto(lambda (ls)

(call/cc(lambda (salir)

(let prod ((ls ls))(cond

((null? ls) 1)((= (car ls) 0) (salir 0))(else (* (car ls)(prod (cdr ls))))

))))));=> Value: producto

(producto '()) ;=> Value: 1(producto '(1 2 3 4 5)) ;=> Value: 120(producto '(2 4 5 0 5 6 8 3 5 7)) ;=> Value: 0

Ejemplo 2: call/cc

(define list-length(lambda (ls)

(call/cc(lambda (retorno)

(letrec((len (lambda (ls)

(cond((null? ls) 0)((pair? ls) (+ 1 (len (cdr ls))))(else (retorno #f))

)))) (len ls)

)))));=> Value: list-length

(list-length '(a b c d e)) ;=> Value: 5(list-length '(a . b)) ;=> Value: ()

40

Ejemplo de memorizar una continuación

(define retry #f);=> retry

(define factorial(lambda (x)

(if (= x 0)(call/cc (lambda (k) (set! retry k) 1))(* x (factorial (- x 1)))

)));=> factorial

(factorial 4) ;=> 24retry ;=> #[continuation 13](retry 2) ;=> 48

4.5 Ligado de Variables en Scheme

Referencia a variables, lambda, formas let y asignación

41

a) Referencia a una Variable

• variableretorno: valor de la variable

• Cualquier identificador no citada en una expresión es una palabra clave o una referencia a una variable.

• Una palabra clave tiene un ligado léxico; sino es una referencia a una variable.

Ligado de Referencias a Variables

• Es un error evaluar una referencia a una variable de nivel superior antes de definirla.

• No lo es que una referencia a una variable aparezca dentro de una expresión no evaluada.

42

Ejemplo de Referencias a Variables

list ;=> #<procedure>

(define x ‘a) ;=> x(list x x) ;=> (a a)

(let ((x ‘b)) (list x x)) ;=> (b b)

(define f (lambda (x) (g x))) ;=> f(define g (lambda (x) (+ x x))) ;=> g(f 3) ;=> 6

• (lambda formales exp1 exp2 ...)retorno: un procedimiento

• Permite crear procedimientos• En el momento de la evaluación se ligan los

parámetros formales a los actuales y las variables libres a sus valores.

• Parámetros formales se especifican en tres formas:lista propia o impropia o variables única

• Cuerpo se evalúa secuencialmente.

b) Lambda

43

Ejemplo de Lambda

((lambda (x y) (+ x y)) 3 4) ;=> 7

((lambda (x . y) (list x y)) 3 4) ;=> (3 (4))

((lambda x x) 3 4) ;=> (3 4)

c) Ligado Local

• Formas más conocidas de ligado local son:– let– let*– letrec

44

Forma let• (let ((var val)...) exp1 exp2 ...)retorno: valor de última expresión

• Cada variable se liga al valor correspondiente.• Las expresiones de valor en la definición están

fuera del ámbito de las variables.• No se asume ningún orden particular de

evaluación de las expresiones del cuerpo.• Se recomienda su uso para valores

independientes y donde no importa orden de evaluación.

Forma let*• (let* ((var val)...) exp1 exp2 ...)retorno: valor de última expresión

• Similar a let, donde se asegura que expresiones se evalúan de izquierda a derecha.

• Cada expresión está dentro del ámbito de las variables de la izquierda.

• Se recomienda su uso si hay una dependencia lineal entre los valores o el orden de evaluación es importante.

45

Forma letrec• (letrec ((var val)...) exp1 exp2 ...)retorno: valor de última expresión

• Similar a let, excepto que todos los valores están dentro del ámbito de todas las variables (permite definición de procedimientos mutuamente recursivos).

• Orden de evaluación no está especificado.• Se recomienda su uso si hay una dependencia

circular entre las variables y sus valores y el orden de evaluación no es importante.

Ejemplo de ligado local

(let ((x 1) (y 2))(let ((x y) (y x))

(list x y))) ;=> (2 1)

(let ((x 1) (y 2))(let* ((x y) (y x))

(list x y))) ;=> (2 2)

(letrec ((suma (lambda (x)(if (zero? X)

0(+ x (suma (- x 1)))))))

(suma 10));=> 55

46

d) Definición de Variables• (define var exp)retorno: no especificado

• Normalmente se usan como definiciones de nivel superior, i.e. fuera de cualquier forma let o lambda, siendo en este caso visible en cualquier expresión donde no sea sombreada por una variable local.

• También están permitidas la definiciones internas al comienzo del cuerpo de una expresión lambda o derivada.

Definiciones Internas

• La expresión:

• Se transforma en:

(lambda formales(define var val) ...exp1 exp2 ...)

(lambda formales(letrec ((var val) ...)

exp1 exp2 ...))

47

Definiciones Abreviadas para Procedimientos

• (define (var0 var1 ...) exp1 exp2 ...)retorno: no especificado

• (define (var0 . varr) exp1 exp2 ...)retorno: no especificado

• (define (var0 var1 var2 ... varn .varr)exp1 exp2 ...)

retorno: no especificado

Ejemplo de Definiciones

(define x 3)x ;=> 3

(define f (lambda (x) (+ x 1)));=> f

(let ((x 2))(define f (lambda (y) (+ y x)))(f 3))

;=> 5

(f 3) ;=> 4

48

Asignación• (set! var exp)retorno: no especificado

• Cambia el valor ligado a la variable se cambia al valor de la expresión.

• Evaluaciones posteriores evalúan al nuevo valor.

• set! no establece un nuevo ligado, sino que cambia uno existente.

• Son útiles para actualizar un estado y para crear estructuras recursivas.

4.6 Operaciones de Control en Scheme

Constantes, citaciones, secuenciación, condicionales y

formas repetitivas

49

a) Constantes

• constanteretorno: constante

• Cualquier constante evalúa hacia si mismo.• Son constantes los números, booleanos,

caracteres y strings.• Las constantes son inmutables (no se pueden

cambiar con asignación)

b) Citaciones

• (quote obj)(ó ‘obj)retorno: obj

• ‘obj es equivalente a (quote obj)• Quote inhibe la evaluación de obj• Citación no es necesaria para una constante

50

Cuasi- Citación

• (quasiquote obj) (ó `obj)retorno: ver explicación

• (unquote obj) (ó ,obj)retorno: ver explicación

• (unquote-splicing obj) (ó ,@obj)retorno: ver explicación

Expresiones Cuasi-citadas

• quasiquote es similar a quote, salvo que permite descitar parte del texto (usando unquote o unquote-splicing).

• Dentro de una expresión cuasi-citada se permite la evaluación de expresiones que han sido descitadas, cuyo resultado es el que aparece en el texto.

• unquote o unquote-splicing son sólo válidos dentro de un quasiquote.

51

Ejemplos de Citaciones

‘(* 2 3) ;=> (+ 2 3)`(+ 2 3) ;=> (+ 2 3)`((+ 2 ,(* 3 4)) ;=> (+ 2 12)

(let ((a 1) (b 2))`(,a . ,b)) ;=> (1 . 2)

`(list ,(list 1 2 3)) ;=> (list (1 2 3))`(list ,@(list 1 2 3)) ;=> (list 1 2 3)

‘`,(cons ‘a ‘b) ;=> `,(cons ‘a ‘b)`‘,(cons ‘a ‘b) ;=> ‘(a . b)

c) Aplicación de Procedimientos

• (proc exp ...)retorno: resultado de aplicar el valor de proc a los valores de exp...

• Aplicación de procedimientos es la estructura básica de Scheme

• Orden de evaluación de expresiones no estáespecificado, pero se hace secuencialmente.

52

apply• (apply proc obj ... lista)retorno: resultado de aplicar proc alos valores de obj … y a los elementos de la lista

• apply invoca proc con obj como primer argumento …, y los elementos de lista como el resto de los argumentos.

• Es útil cuando algunos o todos los argumentos de un procedimiento están en una lista.

Ejemplos de Aplicación de Procedimientos

(+ 3 4) ;=> 7((lambda (x) x) 5) ;=> 5

(apply + ‘(5 -1 3 5)) ;=> 12

(apply min 5 1 3 ‘(5 -1 3 5)) ;=> -1

53

d) Secuenciación

• (begin exp1 exp2 ...)retorno: resultado de última

expresión• Expresiones se evalúan de izquierda a derecha.• Se usa para secuenciar asignaciones, E/S y

otras operaciones que causan efectos laterales.• Los cuerpos de lambda, let, let* y letrec,

como también las cláusulas de cond, case ydo, se tratan como se tuvieran implícitamente un begin.

Ejemplo de Secuenciación

(define swap-pair!(lambda (x)

(let ((temp (car x)))(set-car! x (cdr x))(set-cdr! x tmp)x)))

(swap-pair! (cons ‘a ‘b)) ;=> (b . a)

54

e) Condicionales

• (if test consec alt)(if test consec)retorno: el valor de consec o altsegún valor de test

• Si no se especifica alternativa y test evalúa en falso, resultado no está especificado.

not

• (not obj)retorno: #t si obj es falso,

sino #f• not es equivalente a:

• El estándar ANSI/IEEE permite que () y #fsean equivalente, retornando #t para (not‘())

(lambda (x) (if x #f #t)

55

and

• (and exp ...)retorno: ver explicación

• Evalúa expresiones de izquierda a derecha y se detiene tan pronto alguna evalúa en falso.

• Se retorna el valor de la última evaluación.

or

• (or exp ...)retorno: ver explicación

• Evalúa expresiones de izquierda a derecha y se detiene tan pronto alguna evalúa en verdadero.

• Se retorna el valor de la última evaluación.

56

cond (1/2)

• (cond cla1 cla2 ...)retorno: ver explicación

• Cada cláusula, excepto la última, tiene la forma:

• La última cláusula tiene alguna de las formas anteriores o:

� (test)� (test exp1 exp2 …)� (test => exp)

(else exp1 exp2 …)

cond (2/2)

• Las cláusulas se evalúan en orden hasta que alguna evalúa en verdadero, o hasta que se agoten

• Si el test de � evalúa verdadero, el valor de test es retornado.

• Si el test de � evalúa verdadero, el valor de la última expresión es retornado.

• Si el test de � evalúa verdadero, es aplicar el procedimiento de la expresión a test (un argumento)

• Si todas las cláusulas evalúan en falso:– si hay else, se retorna valor de la última expresión– si no hay else, valor no está especificado

57

Ejemplo de cond

(define nota(lambda (x)

(cond((not (symbol? x)))((assq x ‘((juan . 68)(maria . 98)

(diego . 45)(lucia . 55)))=> cdr)

(else 0))))

(nota 40) ;=> #t(nota ‘maria) ;=> 98(nota ‘anastasio) ;=> 0

case• (case exp0 cla1 cla2 ...)retorno: ver explicación

• Cada cláusula tiene la forma:

• Siendo las claves datos diferentes. Se puede poner al final una cláusula que calza todo:

• exp0 se evalúa, luego se busca alguna clave que calce con este valor; el resultado es el valor de la última expresión.

((clave ...)exp1 exp2 …)

(else exp1 exp2 …)

58

Ejemplo de case

(define f(lambda (x)

(case x((1 3 5 7 9) ‘impar)((0 2 4 6 8) ‘par)(else ‘fuera-de-rango))))

(f 3) ;=> impar(f 8) ;=> par(f 14) ;=> fuera-de-rango

f) Recursión e Iteración• (let nombre ((var val) ...)

exp1 exp2 ...)retorno:Valor de última expresión

• Es un constructor general de iteración y recursión.

• Las variables var … son visibles dentro del cuerpo, como en la forma común de let.

• nombre es ligado a un procedimiento que puede iterar o llamarse recursivamente.

• En un nuevo llamado, los argumentos son los nuevos valores de las variables var …

59

Ejemplo de let con nombre

(define divisores ;;; sin recursión de cola(lambda (n)

(let div ((i 2))(cond

((>= i n) ‘())((integer? (/ n i)) (cons i (div (/ n i) i)))(else (div n (+ i 1)))))))

(define divisores ;;; con recursión de cola(lambda (n)

(let div ((i (- n 1) (ls ‘()))(cond

((<= i 1) ‘())((integer? (/ n i)) (div i (cons i ls)))(else (div (- i 1) ls))))))

do• (do ((var val nuevo) ...)

(test res ...) exp ...)retorno:Valor de último res

• Permite una forma iterativa simple.• Lar variables var se ligan inicialmente a val,

y son re-ligadas a nuevo en cada iteración posterior.

• En cada paso se evalúa test. Si evalúa como– #t : se termina evaluando en secuencia res … y

retornando valor de última expresión de res … .– #f: se evalúa en secuencia exp ... y se vuelve a

iterar re-ligando variables a nuevos valores.

60

Ejemplo de do(define factorial

(lambda (n)(do ( (i n (- i 1)) ;; variable i

(a 1 (* a i))) ;; variable a((zero? i) a)))) ;; test

(define divisores(lambda (n)

(do ((i 2 (+ i 1)) ;; variable i(ls ‘() ;; variable ls

(if (integer? (/ n i))(cons i ls)ls)))

((>= i n) ls)))) ;; test

for-each• (for-each proc lista1 lista2 ...)retorno:no especificado

• Similar a map, pero no crea ni retorna una lista con los resultados.

• En cambio, si garantiza orden de aplicación de proc a los elementos de las listas de izquierda a derecha.

61

Ejemplo de for-each

(define comparar(lambda (ls1 ls2)

(let ((cont 0))(for-each

(lambda (x y)(if (= x y)

(set! cont (+ cont 1))))ls1 ls2)

cont)))

(comparar ‘(1 2 3 4 5 6) ‘(2 3 3 4 7 6));=> 3

g) Mapping

• (map proc lista1 lista2 ...)retorno:lista de resultados

• Las listas deben ser del mismo largo.• proc debe aceptar un número de argumentos

igual al número de listas.• map aplica repetitivamente proc tomando

como parámetros un elemento de cada lista.• No está especificado el orden en que se

aplica proc a los elementos de las listas.

62

Ejemplo de map

(map (lambda (x y) (sqrt (* x x) (* y y)))‘(3 5)‘(4 12))

;=> (5 13)

h) Evaluación Retardada

• (delay exp)retorno:una promesa

• (force promesa)retorno:resultado de forzar la promesa

• delay con force se usan juntos para permitir una evaluación perezosa, ahorrando computación.

• La primera vez que se fuerza la promesa se evalúa exp, memorizando su valor; forzados posteriores retornan el valor memorizado.

63

Ejemplo de Evaluación Retardada

;;; define un stream infinito de números naturales

(define stream-car(lambda (s) (car (force s))))

(define stream-cdr(lambda (s) (cdr (force s))))

(define contadores (let prox ((n 1))

(delay (cons n (prox (+ n 1))))))

(stream-car contadores) ;=> 1

(stream-car (stream-cdr contadores)) ;=> 2

i) Evaluación

• (eval obj)retorno: evaluación de obj

como un programa Scheme• obj debe ser un programa válido de Scheme.• El ámbito actual no es visible a obj,

comportándose éste como si estuviera en un nivel superior de otro ambiente.

• No pertenece al estándar de ANSI/IEEE.

64

Ejemplo de eval

(eval 3) ;=> 3

(eval ‘‘(+ 3 4)) ;=> 7

(eval (list ‘+ 3 4)) ;=> 7

4.7 Operaciones sobre Objetosen Scheme

Equivalencias y predicados de tipos, listas, números, caracteres,

strings y vectores

65

a) Equivalencias

• (eq? obj1 obj2)retorno: #t si son idénticos• (eqv? obj1 obj2)retorno: #t si son equivalentes• eqv? es similar a eq?, salvo que no es

dependiente de la implementación, pero es algo más costoso.

• eq? no permite comparar en forma fiable números

equal?• (equal? obj1 obj2)retorno: #t si tienen la mismaestructura y contenido

• equal? es similar a eqv?, salvo que se aplica también para strings, pares y vectores.

• Es más costoso que eqv? y eq?,

66

Ejemplos de Equivalencia

(eq? ‘a ‘a) ;=> #t(eq? 3.1 3.1) ;=> ()(eq? (cons ‘a ‘b)(cons ‘a ‘b)) ;=> ()

(eqv? ‘a ‘a) ;=> #t(eqv? 3.1 3.1) ;=> #t(eqv? (cons ‘a ‘b)(cons ‘a ‘b)) ;=> ()

(equal? ‘a ‘a) ;=> #t(equal? 3.1 3.1) ;=> #t(equal? (cons ‘a ‘b)(cons ‘a ‘b)) ;=> #t

b) Predicados de Tipos• (boolean? obj)retorno: #t si obj #t o diferente de #f

• (null? obj)retorno: #t si obj #f o lista vacia

• (pair? obj)retorno: #t si obj es un par

67

Tipos de Números

• (number? obj)retorno: #t si obj es número

• (complex? obj)retorno: #t si obj es número complejo

• (real? obj)retorno: #t si obj es número real

• (rational? obj)retorno: #t si obj es número racional

• (integer? obj)retorno: #t si obj es número entero

Otros Tipos• (char? obj)retorno: #t si obj es un caracter

• (string? obj)retorno: #t si obj es un string

• (vector? obj)retorno: #t si obj es un vector

• (symbol? obj)retorno: #t si obj es un símbolo

• (procedure? obj)retorno: #t si obj es un procedimiento

68

c) Listas

• El par es la estructura más fundamental de los tipos de objetos

• Los pares normalmente se usan para construir listas

• Las listas son secuencias ordenadas donde cada elemento ocupa el car de un par y el cdrdel par del último elemento es la lista vacía.

• Si no se cumple lo anterior, es una lista impropia

Operadores Básicos con Listas

• (list obj ...)retorno: una lista de elementos obj ...

• (list? obj)retorno: #t si obj es una lista propia

• (length? list)retorno: el número de elementos de list

69

Otros Operadores con Listas

• (list-ref list n)retorno: elemento #n (basado en 0) de

list• (list-tail list n)retorno:el resto de list a partir de elemento #n

• (append list ...)retorno: concatenación de list ...

• (reverse list)retorno: list en orden invertido

Membresía en Listas

• (memq obj list)retorno:el resto de list a partir de elemento obj si es encontrado, sino #f

• (memv obj list)retorno:el resto de list a partir de elemento obj si es encontrado, sino #f

• (member obj list)retorno:el resto de list a partir de elemento obj si es encontrado, sino #f

• Usan eq? y eqv? y equal? respectivamente

70

d) Listas Asociativos

• Una lista asociativa (alist) es una lista propia cuyos elementos son pares.

• Un par tiene la forma (clave . valor)• Asociaciones son útiles para almacenar

información (valor) relacionada con un objeto (clave)

Operadores con Listas Asociativos

• (assq obj alist)retorno: primer elemento de alist cuyocar es equivalente a obj, sino #f

• (assv obj alist)retorno: primer elemento de alist cuyocar es equivalente a obj, sino #f

• (assoc obj alist)retorno: primer elemento de alist cuyocar es equivalente a obj, sino #f

• Usan eq? y eqv? y equal? respectivamente

71

e) Números

• Scheme soporta enteros, racionales, reales y complejos (que definen una jerarquía)

• Los números pueden ser exactos o inexactos• Enteros y racionales pueden soportan precisión

arbitraria• Números inexactos se representan en punto

flotante• Los complejos se representan como un par,

usando coordenadas polares o rectangulares

Operadores con Números

• (exact? num)retorno: #t si num es exacto

• (inexact? num)retorno: #t si num es inexacto

• (= num1 num2 ...)retorno: #t si los números son iguales

• (op real1 real2 ...)retorno: #t si los números cumplen la relación op, con op en {<, >, <=,>=}(no está definido para complejos)

72

Operadores Aritméticos

• (+ num ...)retorno: la suma de los argumentos num...

• (- num)retorno: cambio de signo de num

• (- num1 num2 ...)retorno: substracción a num1 de num2 ...• (* num ...)

retorno: la multiplicación de num...• (/ num)

retorno: recíproco multiplicativo de num• (/ num1 num2 num3 ...)retorno: la división de num1 por la multiplicación

de num2 ...

Predicados con Números

• (zero? num)retorno: #t si num es cero

• (positive? num)retorno: #t si num es positivo

• (negative? num)retorno: #t si num es negativo

• (even? num)retorno: #t si num es par

• (odd? num)retorno: #t si num es impar

73

Operadores con Enteros

• (quotient int1 int2)retorno: el cuociente de int1 y int2• (remainder int1 int2)retorno: el residuo de int1 y int2• (modulo int1 int2)retorno: el módulo entero de int1 y int2• (gcd int ...)

retorno: máximo común divisor de num…• (lcm int ...)

retorno: mínimo común múltiplo de num...

Operadores con Reales

• (truncate real)retorno: truncar a entero hacia cero

• (round real)retorno: rondear a entero más cercano

• (abs real)retorno: valor absoluto

• (max real ...)retorno: máximo de real ...

• (min real ...)retorno: mínimo de real ...

74

Funciones Matemáticas

• (sqrt num)retorno: raíz cuadrada de num

• (exp num)retorno: e elevado a la potencia de num

• (log num)retorno: el logaritmo natural de num

• (sin num)retorno: el seno de num

• (cos num)retorno: el coseno de num

• (tan num)retorno: la tangente de num

f) Caracteres

• Representan objetos atómicos (letras, números, caracteres especiales)

• Se escriben con el prefijo #\• Ejemplos:

#\a carácter ‘a’#\newline cambio de línea#\space espacio en blanco

75

Predicados de Caracteres

• (char=? char1 char2 ...)• (char<? char1 char2 ...)• (char>? char1 char2 ...)• (char<=? char1 char2 ...)• (char>=? char1 char2 ...)retorno: #t si relación es verdadera,

sino #f

• Relaciones son sensibles a mayúsculas• Operadores char-ci@? son insensibles

Otros Operadores con Caracteres

• (char-alphabetic? char)retorno: #t si char es letra

• (char-number? char)retorno: #t si char es número

• (char-lower-case? letter)retorno: #t si char es letra minúscula

• (char-upper-case? letter)retorno: #t si char es letra mayúscula

• (char->integer char)retorno: código del carácter char

• (integer->char int)retorno: carácter con código int

76

g) Strings

• Representan cadenas o secuencias de caracteres

• Se emplean en mensajes o buffers de caracteres

• Se escriben entre citación doble; doble citación se introduce en el texto con \”

• Se indexan con base en 0• Ejemplo:

“Hola”“\”Ohhh\””

Predicados de Strings

• (string=? string1 string2 ...)• (string<? string1 string2 ...)• (string>? string1 string2 ...)• (string<=? string1 string2 ...)• (string>=? string1 string2 ...)retorno: #t si relación es verdadera,

sino #f

• Relaciones son sensibles a mayúsculas• Operadores string-ci@? son insensibles

77

Otros Operadores con Strings

• (string char ...)retorno: un string que contiene char ...

• (make-string n)retorno: un string de n caracteres (indefinido)

• (string-length string)retorno: largo del string

• (string-ref string n)retorno: el carácter n (desde 0) del string

• (string-set! string n char)acción: cambia el carácter n de string a char

• (string-copy string)retorno: una copia de string

• (string-append string ...)retorno: concatenación de string ...

h) Vectores

• Forma más conveniente y eficiente de listas en algunas aplicaciones

• A diferencia de listas, el acceso a un elemento se hace en tiempo constante

• Al igual que strings, se referencian con base 0

• Elementos pueden ser de cualquier tipo• Se escriben como lista, pero precedidos por #

• Ejemplo:#(a b c)

78

Operadores con Vectores

• (vector obj ...)retorno: un vector con objetos obj ...

• (make-vector n)retorno: un vector de largo n

• (vector-length vector)retorno: largo de vector

• (vector-ref vector n)retorno: el elemento n de vector

Más Operadores con Vectores

• (vector-set! vector n obj)acción: define elmto n de vector como obj

• (vector-fill! vector obj)acción: reemplaza cada elemento de vector

con obj• (vector->list vector)retorno: una lista con elementos de vector

• (list->vector list)retorno: una vector con elementos de lista

list

79

4.8 Operaciones de Entrada y Salida en Scheme

Entrada y Salida

• Toda E/S se realiza por puertos.• Un puertos es un puntero a un flujo

(posiblemente infinito) de caracteres (e.g. archivo)

• Un puerto es un objeto de primera clase• El sistema tiene dos puertos por defecto:

entrada y salida estándar (normalmente es el terminal en un ambiente interactivo)

• Cuando se agotan los datos de entrada se retorna el objeto especial eof

80

Operaciones de Entrada (1/2)

• (input-port? obj)retorno: #t si obj es puerto de entrada

• (current-input-port)retorno: puerto de entrada actual

• (open-input-file filename)retorno: nuevo puerto de entrada asociado a archivo filename

• (call-with-input-file file proc)acción: abre file y llama a proc con puerto abierto como parámetro; luego cierra puertoretorno: valor de evaluación de proc

• (close-input-port input-port)acción: cierra puerto de entrada

Operaciones de Entrada (2/2)

• (eof-object? obj)retorno: #t si obj es fin de archivo

• (read)(read input-port)retorno: próximo objeto de input-port

• (read-char)(read-char input-port)retorno: próximo carácter de input-port

(con consumo)• (peek-char)

(peek-char input-port)retorno: próximo carácter de input-port

(sin consumo)

81

Ejemplos de Entrada

(input-port? ‘(a b c)) => unspecified(input-port? (current-input-port)) => #t(input-port? (open-input-file “f.dat”)) => #t

(let ((p (open-input-file “mi_archivo”)))(let leer ((x (read p)))

(if (eof-object? x)(begin

(close-input-port p)‘())

(cons x (leer (read x))))))

Otro Ejemplo de Entrada

(define read-word(lambda (p)

(list->string(let leer_entrada ()

(let ((c (peek-char p)))(cond

((eof-object? c) '())((char-alphabetic? c)

(read-char p)(cons c (leer_entrada )))

(else '())))))));=> read-word

(read-word (current-input-port))hola;=> "hola"

82

Operaciones de Salida (1/2)• (output-port? obj)

retorno: #t si obj es puerto de salida• (current-output-port)

retorno: puerto de salida actual• (open-output-file file)

retorno: nueva puerto de salida asociado a archivo file

• (call-with-output-file file proc)acción: abre file y llama a proc con puerto abierto como parámetro; luego cierra puertoretorno: valor de evaluación de proc

• (close-output-port output-port)acción: cierra puerto de salida

Operaciones de Salida (2/2)

• (write obj)(write obj output-port)acción: escribe obj a output-port

• (display obj)(display obj output-port)acción: escribe obj a output-port

• (write-char char)(write-char char output-port)acción: escribe char a output-port

• (newline)(newline output-port)acción: escribe nueva línea a output-port

83

Observaciones a E/S

• write escribe objetos que luego pueden ser leídos con read– Strings se escriben con citación doble– Un carácter se escribe con prefijo #\

• display se usa normalmente para escribir objetos que no serán leídos– Strings y caracteres no escriben doble citación o #\

• write-char y read-char escriben y leen un único carácter sin usar #\

Ejemplo de E/S

(define copy-file(lambda (infile outfile)

(call-with-input-file infile(lambda (iport)

(call-with-output-file outfile(lambda (oport)

(do ((c (read-char iport) (read-char iport)))

((eof-object? c))(write-char c oport))))))))

;=> copy-file

(copy-file “infile” “outfile”);=> #t

84

Operaciones Especiales de E/S

• (transcript-on file)acción: inicia registro en file la sesión interactiva de Scheme

• (transcript-off)acción: termina de registrar sesión

• (load file)acción: carga file leyendo y evaluando secuencialmente las expresiones contenidas.