Lenguajes de Programación

Programación funcional

Roberto Bonvallet

Departamento de Informática
Universidad Técnica Federico Santa Marı́a

Concepto de función

En el paradigma imperativo:
I Una función es una secuencia de instrucciones
I El valor de retorno se obtiene a través de una serie de
manipulaciones de estado
I Existencia de estado implica posibles efectos laterales
I Consecuencia de la arquitectura de von Neumann

Concepto de función

En matemáticas:
I Una función es un mapeo de los elementos de un conjunto a
los de otro: f : A → B
I Generalmente descrita por una expresión o una tabla de
valores
I Evaluación controlada por recursión y expresiones
condicionales
I Libre de efectos laterales

Influencia del paradigma imperativo en la programación I Lenguajes imperativos están diseñados para explotar la arquitectura del computador I Apego a la arquitectura es una restricción innecesaria al proceso de desarrollo de software I Lenguajes diseñados según otros paradigmas son impopulares debido a penalizaciones de rendimiento I Máquina de Turing: modelo matemático para estudiar capacidades y limitaciones del computador .

I No se usa variables ni asignaciones. I Repetición a través de recursión. I Transparencia referencial. . I Funciones son objetos de primera clase.Fundamentos de los lenguajes funcionales I Objetivo: emular las funciones matemáticas lo más posible. I Un programa consiste de definiciones de funciones y aplicaciones de ellas.

Funciones Funciones simples I Ejemplo: cubo(x) ≡ x ∗ x ∗ x I x representa cualquier valor del dominio. cada aparición de un parámetro está ligada a un valor y es considerada constante I Notación lambda para funciones anónimas: λ(x) x ∗ x ∗ x I Evaluación de una función anónima:  λ(x) x ∗ x ∗ x (2) = 8 . pero está fijo en un elemento especı́fico durante la evaluación I Durante la evaluación.

h.Funciones Formas funcionales (funciones de mayor orden) I Reciben funciones como parámetros. i (x) = g (x). Por ejemplo: composición   f ◦ g (x) = f g (x) construcción    g . h(x). o entregan funciones como resultado. j(y ). y . j(z) . i(x) aplicar a todo   α j. (x. z) = j(x).

Comparación entre un programa imperativo y uno funcional I Problema sencillo: aplicar dos funciones a una lista de valores I Programa imperativo: target ← [] for i in source do t1 ← g (i) t2 ← f (t1 ) target. source h  i target ← f g (i) ∀i ∈ source .append(t2 ) end for I Distintas versiones funcionales del mismo programa: target ← α(f  ◦ g . source)  target ← α λ(x) f g (x) .

Introducción a Scheme Caracterı́sticas: I dialecto de LISP I sintaxis y semántica simples I nombres tienen ámbito estático I no es puramente funcional .

I Las llamadas a funciones se evalúan ası́: 1. 2. . se aplica la función sobre los parámetros. se evalúa los parámetros.Funcionamiento del intérprete de Scheme I Entorno interactivo implementa un ciclo lectura-evaluación-escritura I Se puede cargar las expresiones desde un archivo para facilitar el desarrollo.

Funcionamiento del intérprete de Scheme Ejemplo de sesión interactiva 12 −−> 12 ’(1 2 3 4) −−> ( 1 2 3 4 ) (+ 1 2 3 ) −−> 6 ( s t r i n g − a p p e n d ” h o l a ” ”mundo” ) −−> ” h o l a mundo” .

Sintaxis del lenguaje Scheme utiliza la misma sintaxis para: 1. listas: (1 2 3 4 5) 2. formas sintácticas: ( i f (< x 0 ) x (− x ) ) . llamadas a función: (max 43 −23 15 58 2 1 ) 3.

0 i 5 .14159 22/7 +27. 0 I strings: ” Hola mundo” I caracteres: #\a #\s p a c e I booleanos: #t #f .Constantes literales I Valores literales pueden ser: I números enteros. racionales y complejos: 123456789 3.0−3. 0 @3 . reales.

0 ” Hola mundo” 3 ) I Las listas se pueden anidar: (a (b c ) (d e ( f ) g )) I Las listas se tratan como objetos inmutables .Listas I Notación de listas: (a b c d) I Los elementos pueden ser de cualquier tipo: ( 1 .

Representación interna de las listas I implementadas como listas enlazadas I los nodos se llaman pares o celdas cons I el final de una lista se marca con la lista vacı́a Figura: Representación de (1 2 3 4 5) .

Representación interna de las listas I implementadas como listas enlazadas I los nodos se llaman pares o celdas cons I el final de una lista se marca con la lista vacı́a Figura: Representación de (1 (2) (3 (4 5 6) (7)) ((8))) .

el cdr. .Celdas cons I Las celdas cons son el tipo de datos estructurado fundamental de Scheme. I El campo izquierdo de una celda se denomina el car. I En una lista enlazada propia. las celdas tienen: I un valor en el car. I una referencia a una lista en el cdr. y el campo derecho.

I La función cons permite crear una celda cons definiendo su car y su cdr. y por lo tanto se puede usar para crear listas enlazadas. ( car ’(1 2 3 4 5)) −−> 1 ( cdr ’(1 2 3 4 5)) −−> ( 2 3 4 5) ( cons ’ a ’( b c d )) −−> ( a b c d) .Celdas cons I Las funciones car y cdr obtienen el car y el cdr de una celda.

Listas impropias I Una lista es impropia cuando el cdr de su última celda no es la lista vacı́a. I Las listas impropias se representan usando la notación de par con punto. 5) . Figura: Representación de (1 2 3 4 .

1) . Figura: Representación de ((2 (3 .Listas impropias I Una lista es impropia cuando el cdr de su última celda no es la lista vacı́a. 4) 5) . I Las listas impropias se representan usando la notación de par con punto.

3) . I Las listas impropias se representan usando la notación de par con punto.Listas impropias I Una lista es impropia cuando el cdr de su última celda no es la lista vacı́a. 2) . 1) . Figura: Representación de (((() .

.Llamadas a funciones I Llamadas a funciones utilizan la misma notación que las listas: ( funcion arg1 arg2 . argN ) I Para evitar que una lista sea evaluada como función. se utiliza el operador de citado: (a b c d) error : ‘ a ’ no e s una f u n c i o n ( quote ( a b c d )) −−> ( a b c d ) ’( a b c d) −−> ( a b c d ) . .

Funciones aritméticas I Scheme provee las funciones aritméticas elementales +. −. ∗ y /: (+ 2 −3) −−> −1 (∗ 1 2 3 4 5) −−> 120 (+ ( ∗ 3 3 ) ( ∗ 4 4 ) ) −−> 25 (− ( / 81 9 ) ( ∗ ) (+)) −−> 8 I Notación prefija evita ambigüedad en la evaluación. .

. . ) I Ejemplo: ( lambda ( x y ) (+ ( ∗ x x ) ( ∗ y y ) ) ) −−> #<p r o c e d u r e > ( ( lambda ( x y ) (+ ( ∗ x x ) ( ∗ y y ) ) ) 3 4 ) −−> 25 . .Funciones anónimas I La forma sintáctica lambda permite definir funciones anónimas. I Sintaxis: ( lambda ( a r g 1 a r g 2 . ) e x p r 1 e x p r 2 . .

. a r g N .Sintaxis alternativas de lambda I Guarda en args la lista de todos los argumentos: ( lambda a r g s e x p r 1 e x p r 2 . ) I Guarda en rest todos los argumentos adicionales: ( lambda ( a r g 1 . . . . . . r e s t ) e x p r 1 e x p r 2 . ) .

. . 0 . . I Sintaxis: ( let (( var1 val1) ( var2 val2) . ) expr1 expr2 . .Ligados locales I La forma sintáctica let establece ligados de nombres locales. 1 6 6 6 6 6 6 6 6 6 6 7 ( ( lambda ( x y ) ( l e t ( ( x−squared ( ∗ x x ) ) ( y−squared ( ∗ y y ) ) ) ( s q r t (+ x−squared y−squared ) ) ) ) 5 12) −−> 1 3 . I Nombres ligados con let son visibles sólo en el cuerpo del let. ) I Ejemplo: ( l e t ( ( a 17) ( b 31)) (+ ( ∗ 1/2 a b ) ( ∗ 1/3 a b ) ) ) −−> 4 3 9 .

Definiciones de nivel superior I La forma sintáctica define liga un nombre a una expresión. I Sintaxis: ( d e f i n e nombre e x p r ) I Ejemplo: ( d e f i n e n 25) ( d e f i n e s q u a r e ( lambda ( x ) ( ∗ x x ) ) ) ( square n) −−> 625 .

I Sintaxis: ( i f condicion consecuencia al t e r na t iv a ) I Ejemplo: ( define signo ( lambda ( x ) ( i f (>= x 0 ) ’ p o s i t i v o ’ n e g a t i v o ) ) ) ( s i g n o −2) −−> n e g a t i v o ( s i g n o 5) −−> p o s i t i v o .Expresiones condicionales simples I La forma sintáctica if permite evaluar una expresión de manera condicional.

) I Cada cláusula tiene alguna de estas formas: 1. (condicion) 2.) . .Expresiones condicionales múltiples I La forma sintáctica cond permite evaluar una expresión usando distintos casos. (condicion => expr) I La última cláusula puede tener la forma: 4. ( else expr 1 expr2 . I Sintaxis: ( cond c l a u s u l a 1 c l a u s u l a 2 . .. (condicion expr 1 expr2 ....) 3.

0 0 ) ) ((<= income 3 0 0 0 0 ) (+ ( ∗ (− income 2 0 0 0 0 ) . 2 1 ) 2 6 0 0 . 0 5 ) ) ((<= income 2 0 0 0 0 ) (+ ( ∗ (− income 1 0 0 0 0 ) .Ejemplo de uso de cond ( d e f i n e income−tax ( lambda ( income ) ( cond ((<= income 1 0 0 0 0 ) ( ∗ income . 0 8 ) 5 0 0 . 0 0 ) ) ( else (+ ( ∗ (− income 3 0 0 0 0 ) . 1 3 ) 1 3 0 0 . 0 0 ) ) ))) .

or y not.Evaluación de valores de verdad I Todos los objetos son considerados verdaderos. los predicados lógicos tienen nombres terminados en ?. I and y or hacen cortocircuito. I Existen las formas sintácticas and. excepto #f. . I En general.

Ejemplos de valores de verdad ( i f 1 ’ true ’ fals e ) −−> t r u e ( i f ’() ’ true ’ fals e ) −−> t r u e ( i f #f ’ t r u e ’ f a l s e ) −−> f a l s e ( not #t ) −−> #f ( not ” f a l s e ” ) −−> #f ( or ) −−> #f ( or #f #t ) −−> #t ( or #f ’ a #t ) −−> ’ a .

Ejemplos de predicados lógicos (< 1 2 3 4 5 ) −−> #t ( null ? ’()) −−> #t ( null ? ’(1 2 3)) −−> #f ( p a i r ? ’(8 . . ” ) −−> #f . 2)) −−> #t ( eqv ? 3 2 ) −−> #f ( number ? 1 5 ) −−> #t ( l i s t ? ”Veamos s i s o y una l i s t a . .

y elimina la necesidad de usar variables de control. I Ejemplo: ( d e f i n e length ( lambda ( l s ) ( i f ( null ? ls ) 0 (+ 1 ( l e n g t h ( c d r l s ) ) ) ) ) ) ( length ’ ( ) ) −−> 0 ( length ’( a b c ) ) −−> 3 .Recursión simple I En Scheme. un paso de recursión. I La recursión es más general que construcciones tipo for o while. I Una función recursiva debe tener: 1. un caso base. y 2. la iteración se hace usando recursión.