Programación Funcional
      con Scheme


          Por: Óscar López, M.Sc.
       olopez@uniandino.com.co
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




                   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
                   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


                   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>)

                    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 libre
   2. 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-η
                       OALP-2005 All Rights Reserved
Evolución de LISP y Scheme
                LISP
               (1958)

  Scheme
   (1974)
                                               Common LISP
                                                  (1984)



                                               Common LISP
                                                ANSI X3.226
                                                  (1994)
 Scheme R6RS
    (2006)
                                                              CLOS
               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
                     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

                        OALP-2005 All Rights Reserved
Tipos de Datos
         Tipo                                 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))

                        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-expresiones
     2. 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)

                       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)

              OALP-2005 All Rights Reserved
Convenciones
         Convención                                        Ejemplos
nulo                                   '()
comentarios                            ;
cualquier valor distinto de #f         #t
es verdadero                           (if (and 0 '()) "mal uso")
nombres en minúsculas                  (make-vector 5)
separados por guiones                  (make-hash-table 'equal)
conversiones                           (number->string 10)
predicados                             (null? '(1 2 3))
operaciones destructivas               (define x 0)
(asignación)                           (set! x 1)
comparaciones                          (char>=? #z #a)
                           OALP-2005 All Rights Reserved
Formas Especiales
(and bool-exp1     ;; también case
     ...           (cond ((bool-exp1) eval-exp1)
     bool-expn)          ...
                         ((bool-expn) eval-expn)
(or bool-exp1            (else eval-exp))
    ...
    bool-expn)
                   ;; también let* y letrec
;; también when    (let ((var1 exp1)
;; y unless              ...
(if (bool-exp)           (varn expn))
  then-exp           use-var1-...-varn)
  else-exp)

                  OALP-2005 All Rights Reserved
Formas Especiales: Ejemplos
(and #t #f (/ 1 0))                    (let ((x 2)
                                             (y 3))
(or   #f #t (/ 1 0))                     (* x y))

(if (= 1 1)                            (let* ((x 2)
    "then-exp"                                (y (+ x 1)))
    (/ 1 0))                             (* x y))

(define a 1)                           (letrec ((y x)
(cond ((= a 1) "uno")                           (x 5))
      ((= a 2) "dos")                    x)
      (else "else"))

                       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)
                       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")))
                     OALP-2005 All Rights Reserved
Procesos Recursivos Lineales
      (define (factorial n)
        (if (= n 1)
            1
            (* n (factorial (- n 1)))))




               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))))))




               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)))




                         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 Scheme
    son 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
                      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)))
                       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


                     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)

                             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!
                          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)
                   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
                     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)

                     OALP-2005 All Rights Reserved
Listas: Ejemplos
(cons 1                  (car '(1 2 3 4 5))                 (cadr '(1 2 3 4 5))
  (cons 2                1                                  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
                            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
                      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)))

                       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

                        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)))
               OALP-2005 All Rights Reserved
Bibliografía
1.   Theo D’Hondt y Wolfgang De Meuter. “Scheme in 2 days”.
     Vrije Universiteit Brussel
2.   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.ht
     ml
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
                       OALP-2005 All Rights Reserved

Programación Funcional con Scheme

  • 1.
    Programación Funcional con Scheme Por: Óscar López, M.Sc. olopez@uniandino.com.co
  • 2.
    Programación Funcional • Unparadigma 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 OALP-2005 All Rights Reserved
  • 3.
    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 OALP-2005 All Rights Reserved
  • 4.
    Cálculo-λ • Modelo matemáticoformal 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 OALP-2005 All Rights Reserved
  • 5.
    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>) OALP-2005 All Rights Reserved
  • 6.
    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 libre 2. 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-η OALP-2005 All Rights Reserved
  • 7.
    Evolución de LISPy Scheme LISP (1958) Scheme (1974) Common LISP (1984) Common LISP ANSI X3.226 (1994) Scheme R6RS (2006) CLOS OALP-2005 All Rights Reserved
  • 8.
    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 OALP-2005 All Rights Reserved
  • 9.
    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 OALP-2005 All Rights Reserved
  • 10.
    Tipos de Datos Tipo 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)) OALP-2005 All Rights Reserved
  • 11.
    Expresiones-S • Son unaconvenció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-expresiones 2. 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) OALP-2005 All Rights Reserved
  • 12.
    Expresiones-S: Ejemplos (+ 11) (/ (+ (sqr 3) 1) (* 3 4 5)) (or (>= 7 5) (not (< 3 8))) ((if (zero? 0) + *) 7 5) OALP-2005 All Rights Reserved
  • 13.
    Convenciones Convención Ejemplos nulo '() comentarios ; cualquier valor distinto de #f #t es verdadero (if (and 0 '()) "mal uso") nombres en minúsculas (make-vector 5) separados por guiones (make-hash-table 'equal) conversiones (number->string 10) predicados (null? '(1 2 3)) operaciones destructivas (define x 0) (asignación) (set! x 1) comparaciones (char>=? #z #a) OALP-2005 All Rights Reserved
  • 14.
    Formas Especiales (and bool-exp1 ;; también case ... (cond ((bool-exp1) eval-exp1) bool-expn) ... ((bool-expn) eval-expn) (or bool-exp1 (else eval-exp)) ... bool-expn) ;; también let* y letrec ;; también when (let ((var1 exp1) ;; y unless ... (if (bool-exp) (varn expn)) then-exp use-var1-...-varn) else-exp) OALP-2005 All Rights Reserved
  • 15.
    Formas Especiales: Ejemplos (and#t #f (/ 1 0)) (let ((x 2) (y 3)) (or #f #t (/ 1 0)) (* x y)) (if (= 1 1) (let* ((x 2) "then-exp" (y (+ x 1))) (/ 1 0)) (* x y)) (define a 1) (letrec ((y x) (cond ((= a 1) "uno") (x 5)) ((= a 2) "dos") x) (else "else")) OALP-2005 All Rights Reserved
  • 16.
    Definiciones • Scheme usala 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) OALP-2005 All Rights Reserved
  • 17.
    Definiciones: Ejemplos (define x7) (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"))) OALP-2005 All Rights Reserved
  • 18.
    Procesos Recursivos Lineales (define (factorial n) (if (= n 1) 1 (* n (factorial (- n 1))))) OALP-2005 All Rights Reserved
  • 19.
    Procesos Recursivos Arbóreos (define (fib n) (cond ((zero? n) 0) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2)))))) OALP-2005 All Rights Reserved
  • 20.
    Procesos Iterativos (define (factorialn) (fact-iter 1 1 n)) (define (fact-iter producto contador n) (if (> contador n) producto (fact-iter (* contador producto) (+ contador 1) n))) OALP-2005 All Rights Reserved
  • 21.
    Expresiones Lambda • Similaresa sus contrapartes en el cálculo-λ, son funciones anónimas de la forma: (lambda (<parámetros-formales>) <cuerpo>) • Sin embargo, las expresiones lambda de Scheme son 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 OALP-2005 All Rights Reserved
  • 22.
    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))) OALP-2005 All Rights Reserved
  • 23.
    Currying • Técnica quepermite 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 OALP-2005 All Rights Reserved
  • 24.
    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) OALP-2005 All Rights Reserved
  • 25.
    Combinador-Y • Conocido comoun “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! OALP-2005 All Rights Reserved
  • 26.
    Combinador-Y: Ejemplos (define (YX) ((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) OALP-2005 All Rights Reserved
  • 27.
    Listas • Recordar: LISPsignifica 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 OALP-2005 All Rights Reserved
  • 28.
    Listas • Las listasse 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) OALP-2005 All Rights Reserved
  • 29.
    Listas: Ejemplos (cons 1 (car '(1 2 3 4 5)) (cadr '(1 2 3 4 5)) (cons 2 1 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 OALP-2005 All Rights Reserved
  • 30.
    Funciones de OrdenSuperior • 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 OALP-2005 All Rights Reserved
  • 31.
    Funciones de OrdenSuperior: 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))) OALP-2005 All Rights Reserved
  • 32.
    Evaluación Perezosa • Unaexpresió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 OALP-2005 All Rights Reserved
  • 33.
    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))) OALP-2005 All Rights Reserved
  • 34.
    Bibliografía 1. Theo D’Hondt y Wolfgang De Meuter. “Scheme in 2 days”. Vrije Universiteit Brussel 2. 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.ht ml 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 OALP-2005 All Rights Reserved