programación funcional con scheme

34
Programación Funcional con Scheme Por: Óscar López, M.Sc. [email protected]

Upload: oscar-lopez

Post on 04-Jul-2015

4.244 views

Category:

Technology


3 download

DESCRIPTION

Introducción a la programación funcional usando Scheme, un dialecto de Lisp

TRANSCRIPT

Page 1: Programación Funcional con Scheme

Programación Funcionalcon Scheme

Por: Óscar López, [email protected]

Page 2: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Programación Funcional

• Un paradigma de programación, donde toda computación es resultado de evaluar funciones matemáticas

• Enfatiza la evaluación de expresiones, no la ejecución de instrucciones

• Las funciones son objetos de primer nivel

Page 3: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Ventajas y Características

• No hay operador de asignación• Una vez se fija el valor de una variable, no

se puede cambiar• No hay efectos secundarios• Transparencia referencial• Ideal para programación concurrente• No hay bucles• Facilita formalización y verificación

matemática

Page 4: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Cálculo-λ

• Modelo matemático formal de computación

• Ideado por Alonzo Church y Stephen Kleene en la década de 1930

• Define las funciones computables• Equivalente a la Máquina de Turing• Es el lenguaje de programación universal

más pequeño

Page 5: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Cálculo-λ: Definición Formal

• Definimos un conjunto infinito enumerable de identificadores {a, b, ..., y, z, x1, x2, ...}

• El conjunto de todas las expresiones lambda puede ser descrito por:1. <expr> ::= <identificador>2. <expr> ::= (λ <identificador> . <expr>) 3. <expr> ::= (<expr> <expr>)

Page 6: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Cálculo-λ: Definición Formal• La ligadura de ocurrencias de variables está definida por

las siguientes reglas:1. En una expresión de la forma V, donde V es una

variable, esta V es la única ocurrencia libre2. En una expresión de la forma λ V. E las ocurrencias

libres son las ocurrencias libres en E, exceptuando aquellas que estén en V. En este caso se dice que las ocurrencias de V en E están ligadas por el λ antes de V

3. En una expresión de la forma (E E') las ocurrencias libres son las ocurrencias libres en E y E'

• Se definen las siguientes transformaciones sobre expresiones lambda: conversión-α, reducción-β, conversión-η

Page 7: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Evolución de LISP y SchemeLISP

(1958)

Scheme(1974)

Common LISP(1984)

Common LISPANSI X3.226

(1994)Scheme R6RS

(2006)

CLOS

Page 8: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Características de Scheme• Estándar minimalista• Variables con alcance léxico• Recursión de cola es mandatoria• Sistema de macros higiénicos• Promueve un estilo de programación funcional• Los programas son datos y los datos son

programas• Continuaciones explícitas• Tipos dinámicos• Recolector de basura• Compilación nativa o máquina virtual

Page 9: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Entorno de Programación

• Un “mundo” que siempre está en el REPL• Lectura: chequea la

sintaxis de una expresión

• Evaluación: ejecuta la expresión

• Impresión: muestra el resultado de la ejecución

• El REPL se ejecuta en el contexto de un entorno global; puede visualizarse como un diccionario que asocia nombres a valores

Page 10: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Tipos de DatosTipo Ejemplos

booleano #t #f

entero 1 -2 3 42

racional 1/4 36/8

real 3.1416 1.2e+4

complejo 0+i 2+3i

carácter #\c #\space #\tab #\newline

símbolo 'var 'xyz

cadena "¡Hola, Mundo!"

lista '(1 2 3 4 5)

vector #(1 2 3 4 5)

estructura (define-struct persona (nombre cc dir tel))

Page 11: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Expresiones-S• Son una convención para representar datos o

expresiones en un programa• Se construyen usando notación prefija (polaca,

funcional) y paréntesis• Pueden estar arbitrariamente anidadas• Están conformadas por átomos y pares (celdas) cons• Cuando una expresión-s denota la aplicación de un

procedimiento, se evalúa en orden aplicativo:1. Se evalúan todas las sub-expresiones2. Se aplica el procedimiento resultado de evaluar la

sub-expresión que está más a la izquierda (el operador) a los argumentos, que son los valores de las demás sub-expresiones (los operandos)

Page 12: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Expresiones-S: Ejemplos

(+ 1 1)

(/ (+ (sqr 3) 1)

(* 3 4 5))

(or (>= 7 5)

(not (< 3 8)))

((if (zero? 0) + *) 7 5)

Page 13: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

ConvencionesConvención Ejemplos

nulo '()

comentarios ;

cualquier valor distinto de #fes verdadero

#t

(if (and 0 '()) "mal uso")

nombres en minúsculas separados por guiones

(make-vector 5)

(make-hash-table 'equal)

conversiones (number->string 10)

predicados (null? '(1 2 3))

operaciones destructivas (asignación)

(define x 0)

(set! x 1)

comparaciones (char>=? #\z #\a)

Page 14: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Formas Especiales;; también case

(cond ((bool-exp1) eval-exp1)

...

((bool-expn) eval-expn)

(else eval-exp))

;; también let* y letrec

(let ((var1 exp1)

...

(varn expn))

use-var1-...-varn)

(and bool-exp1

...

bool-expn)

(or bool-exp1

...

bool-expn)

;; también when

;; y unless

(if (bool-exp)

then-exp

else-exp)

Page 15: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Formas Especiales: Ejemplos(let ((x 2)

(y 3))

(* x y))

(let* ((x 2)

(y (+ x 1)))

(* x y))

(letrec ((y x)

(x 5))

x)

(and #t #f (/ 1 0))

(or #f #t (/ 1 0))

(if (= 1 1)

"then-exp"

(/ 1 0))

(define a 1)

(cond ((= a 1) "uno")

((= a 2) "dos")

(else "else"))

Page 16: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Definiciones• Scheme usa la siguiente construcción para asociarle un

nombre a un valor:(define <nombre-nuevo> <valor-inicial>)

• Las parejas nombre/valor son almacenadas y buscadas en el diccionario que constituye el entorno global de ejecución

• Es posible asociar un nombre a: valores constantes, el resultado de evaluar otras expresiones, procedimientos, etc.

• Cuando se define un nuevo procedimiento, éste tendrásu propio entorno local de ejecución

• Las definiciones se pueden anidar (estructura de bloque)

Page 17: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Definiciones: Ejemplos(define x 7)

(define y (* x x))

(define suma +)

(define (pitagoras x y)(sqrt (+ (sqr x) (sqr y))))

(define (es-par n)(define (par?)(if (= (modulo n 2) 0) #t #f))

(if (par?)(print "es par")(print "es impar")))

Page 18: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Procesos Recursivos Lineales(define (factorial n)

(if (= n 1)

1

(* n (factorial (- n 1)))))

Page 19: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Procesos Recursivos Arbóreos(define (fib n)

(cond ((zero? n) 0)

((= n 1) 1)

(else (+ (fib (- n 1))

(fib (- n 2))))))

Page 20: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Procesos Iterativos

(define (factorial n)(fact-iter 1 1 n))

(define (fact-iter producto contador n)(if (> contador n)

producto(fact-iter (* contador producto)

(+ contador 1) n)))

Page 21: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Expresiones Lambda• Similares a sus contrapartes en el cálculo-λ, son

funciones anónimas de la forma:(lambda (<parámetros-formales>) <cuerpo>)

• Sin embargo, las expresiones lambda de Schemeson formas especiales que pueden recibir más de un parámetro

• Al evaluarlas, retornan un procedimiento• El entorno en el que la expresión lambda fue

evaluada es recordado como parte del procedimiento retornado

• La definición de una función y la asignación de un nombre a ésta no siempre ocurren de manera simultánea

Page 22: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Expresiones Lambda: Ejemplos(lambda (x) (* x x))

((lambda (x) (* x x)) 8)

(define cuadrado(lambda (x) (* x x)))

(cuadrado 8)

(define (cuadrado x)(* x x))

(cuadrado 8)

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

(f 3)))

Page 23: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Currying

• Técnica que permite transformar una función que recibe múltiples argumentos en una secuencia de funciones que reciben un solo argumento

• Nombrada en honor al lógico Haskell Curry• La clave está en recibir el primer argumento,

retornar una función que recibe el siguiente argumento y así sucesivamente

• En ocasiones puede ser útil disponer de las funciones “incompletas” que se obtienen cuando no se proporcionan todos los argumentos

Page 24: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Currying: Ejemplos(define (pitagoras? a b c)(= (sqr a) (+ (sqr b) (sqr c))))

(pitagoras? 5 3 4)

(define pitagoras?(lambda (a)

(lambda (b)(lambda (c)

(= (sqr a) (+ (sqr b) (sqr c)))))))(((pitagoras? 5) 3) 4)

(define por-n(lambda (factor)

(lambda (numero)(* factor numero))))

(define por-2 (por-n 2))(por-2 192)

(define por-23 (por-n 23))(por-23 86)

Page 25: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Combinador-Y• Conocido como un “combinador de punto fijo” en términos

matemáticos; es una función que computa puntos fijos de otras funciones

• Un punto fijo es un valor que permanece “fijo” después de aplicar una función. Formalmente: x es un punto fijo de una función f si f(x) = x

• En algunas formalizaciones matemáticas, como el cálculo-λ, todas las funciones tienen un punto fijo

• Haskell Curry descubrió la función Y del cálculo-λ, que computa un punto fijo para cualquier función que se le proporcione

• Formalmente: Y = λf.(λx.(f (x x)) λx.(f (x x))) . Cumple con la propiedad: ∀f f(Y(f)) = Y(f)

• Utilidad práctica: ¡permite definir funciones recursivas anónimas!

Page 26: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Combinador-Y: Ejemplos(define (Y X)((lambda (proc)

(proc proc))(lambda (proc)(X (lambda (arg)

((proc proc) arg))))))

(define factorial(Y (lambda (fact)

(lambda (n)(if (= n 1)

1(* n (fact (- n 1))))))))

(factorial 5)

Page 27: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Listas

• Recordar: LISP significa List Processor• Las listas son la estructura de datos más

importante en Scheme, pero no son fundamentales

• En cambio, los pares (celdas) cons si son fundamentales

• Los procedimientos primitivos usados para manipular pares son:• cons : recibe dos argumentos y retorna un par• car : retorna el primer componente de un par• cdr : retorna el segundo componente de un par

Page 28: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Listas

• Las listas se construyen a partir de sucesivas aplicaciones de cons, donde el primer elemento es un valor y el segundo un par o nulo

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 '())))))

• Alternativamente, también se pueden crear listas usando las siguientes formas especiales:

(list 1 2 3 4 5)

'(1 2 3 4 5)

Page 29: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Listas: Ejemplos

(car '(1 2 3 4 5))1

(cadr '(1 2 3 4 5))2

(cons 1 (cons 2 (cons 3 (cons 4 (cons 5

'())))))

(cdr '(1 2 3 4 5)) (cdar'((1 2) (3 4) (5 6)))

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

5

Page 30: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Funciones de Orden Superior• Reciben una función como argumento o retornan

una función como resultado• Un concepto originado en las matemáticas. Por

ejemplo, las derivadas e integrales son funciones de orden superior

• Ejemplos de uso:• Una función que requiere otra función como

parámetro es una plantilla, donde la función recibida modifica su comportamiento

• Si las funciones son cerraduras, pueden emplearse para definir estructuras de control

• Útiles para construir iteradores y enumeradores sobre estructuras de datos

Page 31: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Funciones de Orden Superior: Ejemplos

(define (f x) (sqr x))

(define (g x) (+ x 1))

(define h1 (compose f g))

(define h2 (compose g f))

(h1 5)

(h2 5)

(map + '(1 2 3) '(4 5 6))

(filter (lambda (x) (> x 5)) '(0 2 4 6 8 10))

(mergesort '(-1 7 10 0 2 2 -3)

(lambda (x y) (>= x y)))

Page 32: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Evaluación Perezosa• Una expresión no se evalúa de inmediato, la evaluación se

pospone hasta el momento en que sea necesaria• Scheme permite usar evaluación estricta o perezosa, pero

esta última debe programarse de manera explícita:• (delay <expresión>) retorna una promesa, que puede

ser evaluada más adelante• (force <promesa>) evalúa una promesa y retorna el

valor resultante• El valor de una promesa es recordado, de tal forma que si

force es llamado nuevamente, se retorna el valor previamente computado

• Útil para trabajar con estructuras de datos infinitas• Permite “pegar” programas de una forma completamente

distinta

Page 33: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Evaluación Perezosa: Ejemplos

(let ((promesa (delay (+ 1 2))))(list (force promesa) (force promesa)))

(define (next n)(cons n (delay (next (+ n 1)))))

(define a-stream (next 0))

(define head car)(define (tail stream)

(force (cdr stream)))

(head (tail (tail a-stream)))

Page 34: Programación Funcional con Scheme

OALP-2005 All Rights Reserved

Bibliografía1. Theo D’Hondt y Wolfgang De Meuter. “Scheme in 2 days”.

Vrije Universiteit Brussel2. Harold Abelson, Gerald Sussman y Julie Sussman.

“Structure and Interpretation of Computer Programs”. MIT Press

3. John Hughes. “Why Functional Programming Matters”. Institutionen för Datavetenskap, Chalmers Tekniska Högskola

4. Combinador-Y. http://www.ece.uc.edu/~franco/C511/html/Scheme/ycomb.html

5. Teach Yourself Scheme in Fixnum Days. http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme.html

6. Wikipedia. http://en.wikipedia.org/wiki/Main_Page