Tema 3: Características de la programación funcional Sesión 5: El paradigma funcional (1) martes 22 de febrero de 2011 Referencias • Capítulo 1.1.5 SICP: [[http://mitpress.mit.edu/sicp/full-text/book/book-ZH-10.html#%_sec_1.1.5][The Substitution Model for Procedure Application]] • Capítulo 10 PLP: Functional Languages martes 22 de febrero de 2011 Hoy veremos • Historia del paradigma funcional • Características del paradigma funcional puro • Modelo de computación basado en sustitución martes 22 de febrero de 2011 Orígenes históricos • Raíces teóricas, antes de aparecer los ordenadores • 1930s: Alan Turing, Alonzo Church, Stephen Kleene, Emil Post, etc. • Turing: Máquina de Turing, programación imperativa • Kleene y Post: métodos abstractos, sustituciones algebraicas • Church: Cálculo lambda, programación funcional • Modelo de cálculo lambda basado en la definición de funciones y la aplicación de estas funciones a argumentos martes 22 de febrero de 2011 Conceptos de la programación funcional En un sentido estricto, la programación funcional define un programa como una función matemática que convierte unas entradas en unas salidas, sin estado interno ni efectos laterales • Lenguajes funcionales puros: Miranda, Haskell, pH, Sisal, ML... • (1958, John MacCarthy). LISP es el primer lenguaje de alto nivel basado en el paradigma funcional • LISP no es programación funcional pura, tienen algunas instrucciones imperativas que permiten estado local y efectos laterales • LISP lenguaje revolucionario, introduce nuevos conceptos: funciones como objetos primitivos, funciones orden superior, polimorfismo, listas, recursión, símbolos, homogeneidad de datos y programas, bucle “read-eval-print” martes 22 de febrero de 2011 Características de la programación funcional • Programación declarativa: • no hay asignación ni cambio de estado • no hay referencias: identificadores asociados a valores • no hay efectos laterales • Recursión • Funciones como tipos de datos primitivos martes 22 de febrero de 2011 Programación declarativa vs imperativa • Programación imperativa: pasos de ejecución y estado de variables int x = x + 1; int y = y + 3; (define (cuadrado x) (* x x)) • Ejemplo de estado local (no existe en programación declarativa): int function contador () { static int c = 0; c++; return c; } contador(): 1 contador(): 2 contador(): 3 martes 22 de febrero de 2011 Programación declarativa vs imperativa • Programación declarativa: Dentro del ámbito de declaración de las variables x1 … xn todas las ocurrencias de una expresión e que contiene únicamente las variables x1 … xn tienen el mismo valor. • Consecuencia: optimización. Si una expresión e aparece en varios lugares dentro de un mismo ámbito, sólo es necesario evaluarla una vez. (define (f x) ...) (+ (f 2) (f 2)) (define (f x) ...) (define y (f 2)) (+ y y) Una función llamada con los mismos argumentos siempre devuelve el mismo resultado martes 22 de febrero de 2011 Modelo de computación de sustitución • Un modelo computacional es un formalismo (conjunto de reglas) que definen el funcionamiento de un programa. • En los lenguajes funcionales basados en la evaluación de expresiones, el modelo computacional define cuál va a ser el resultado de evaluar una determinada expresión. • El modelo de sustitución se basa en una versión simplificada de la regla de reducción del cálculo lambda. martes 22 de febrero de 2011 Modelo de computación de sustitución • Reglas para evaluar una expresión e de Scheme: • Si e es un valor primitivo, devolver ese mismo valor. • Si e es una variable, devolver su valor asociado. • Si e es una expresión del tipo (f arg1 … argn), donde f el nombre de un procedimiento primitivo (+, -, …), evaluar arg1 … argn y aplicar el procedimiento al resultado. • Si e es una expresión del tipo (f arg1 … argn), donde f es el nombre de un procedimiento compuesto (definido con un define), sustituir f por su cuerpo, reemplazando cada parámetro formal del procedimiento por el correspondiente argumento evaluado. Evaluar la expresión resultante. martes 22 de febrero de 2011 Ejemplo modelo de sustitución (define (double x) (+ x x)) (define (square y) (* y y)) (define (f z) (+ square (double z)) 1)) • Evaluamos (f (+ 2 1)) con orden aplicativo martes 22 de febrero de 2011 Orden normal vs orden aplicativo • Orden aplicativo (Scheme): se evalúan primero los argumentos, luego se sustituye • Orden normal: se realizan todas las sustituciones hasta que se tiene una larga expresión formada por expresiones primitivas; se evalúa entonces • Evaluamos (f (+ 2 1)) con orden normal En programación funcional el orden normal y el orden aplicativo siempre devolverán el mismo resultado martes 22 de febrero de 2011 Orden normal vs orden aplicativo • El orden importa si no tenemos programación funcional pura: (define (zero x) (- x x)) (zero (random 10)) martes 22 de febrero de 2011 Simulación en Scheme (load "simply.scm") (load "order.scm") (def (doble x) (+ x x)) (def (cuadrado x) (* x x)) (def (f z) (+ (cuadrado (doble z)) 1)) (applic (f (+ 2 1))) (normal (f (+ 2 1))) martes 22 de febrero de 2011 Ejercicios • Dada la función: (define (double x) (+ x x)) • Evaluar la expresión (double (* 3 4)) en orden aplicativo y en orden normal. ¿Cuál es más eficiente? • Dada la función: (define (switch (cond ((< x ((= x ((> x x a b c) 0) a) 0) b) 0) c)))) • Evaluar la expresión (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) en orden aplicativo y en orden normal. ¿Cuál es más eficiente? martes 22 de febrero de 2011