Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz,...

23
Tema 6: Programación funcional en Scala Sesión 19: Programación funcional en Scala (3) martes 12 de abril de 2011

Transcript of Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz,...

Page 1: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Tema 6: Programación funcional en Scala

Sesión 19: Programación funcional en Scala (3)

martes 12 de abril de 2011

Page 2: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Referencias

• Programming in Scala. Martin Odersky, Lex Spoon, Bil Venners. Ed. Artima.

• Programming Scala. Dean Wampler, Alex Payne. Ed. O'Reilly.

• Scala by Example. Martin Odersky. November 2010.

• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010.

• The Scala Language Specification. Martin Odersky. November 2010.

martes 12 de abril de 2011

Page 3: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones sobre listas

• Con las operaciones previas se pueden definir funciones similares a las que vimos en Scheme

• Inserción en una lista ordenada:

• Ordenación de una lista:

martes 12 de abril de 2011

Page 4: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones sobre listas

• Con las operaciones previas se pueden definir funciones similares a las que vimos en Scheme

• Inserción en una lista ordenada:

• Ordenación de una lista:

def insert(x: Int, lista: List[Int]) : List[Int] = if (lista.isEmpty) x :: Nil else if (x < lista.head) x :: lista else lista.head :: insert(x, lista.tail)

martes 12 de abril de 2011

Page 5: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones sobre listas

• Con las operaciones previas se pueden definir funciones similares a las que vimos en Scheme

• Inserción en una lista ordenada:

• Ordenación de una lista:

def insert(x: Int, lista: List[Int]) : List[Int] = if (lista.isEmpty) x :: Nil else if (x < lista.head) x :: lista else lista.head :: insert(x, lista.tail)

def sort(lista: List[Int]): List[Int] = if (lista.isEmpty) Nil else insert(lista.head, sort(lista.tail))

martes 12 de abril de 2011

Page 6: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones sobre listas

• Reverse-list:

martes 12 de abril de 2011

Page 7: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones sobre listas

• Reverse-list:

def reverse(l: List[Int]) : List[Int] = if (l == Nil) l else reverse(l.tail) ::: List(l.head)

martes 12 de abril de 2011

Page 8: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Cadenas

• El tipo de Scala es String y se convierte en la clase de Java java.lang.String

• Al igual que las listas son inmutables

• Concatenación con el operador +

• Funciones head, tail, charAt

"hola" + "adios" --> "holaadios"

"hola".head --> h"hola".tail -->"ola""hola".charAt(0) --> 'h'

martes 12 de abril de 2011

Page 9: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Tuplas

• Scala permite construir tuplas de n elementos de distinto tipo

• Es un tipo también inmutable

• La forma de definir una tupla de n tipos es: (tipo1, tipo2,..., tipoN)

• Métodos de acceso al elemento de la tupla ._1, ._2, …

• Ejemplo con una tupla de tres elementos:

val miTupla = (99, "Hola", true)println(miTupla._1)println(miTupla._2)println(miTupla._3)

martes 12 de abril de 2011

Page 10: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Tuplas

• Muy útiles para funciones que tienen que devolver más de un elemento:

martes 12 de abril de 2011

Page 11: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Tuplas

• Muy útiles para funciones que tienen que devolver más de un elemento:

def sumaCadenas(s1: String, s2: String): (String, Int) = (s1+s2, s1.length+s2.length)

martes 12 de abril de 2011

Page 12: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Ámbito de variables

• Una vez definida una variable en un ámbito no podemos volver a definirla

• Sería un error el siguiente script:

• Sí es posible hacerlo en el intérprete, porque cada evaluación de una expresión crea una nuevo ámbito

val a = 1val a = 2 // errorprintln(a)

martes 12 de abril de 2011

Page 13: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Ámbito de variables

• Podemos crear un ámbito interior utilizando llaves:

• Podemos utilizar funciones locales que definen su propio ámbito:

val a = 1;{ val a = 2; println(a)}println(a)

def function1(x : Int) = { def function2(y: Int) = { x*y } function2(3)}function1(2)

martes 12 de abril de 2011

Page 14: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones como objetos de primera clase

• En Scala las funciones son también objetos de primera clase

• Podemos:

• Definir variables y parámetros de tipo función

• Almacenar funciones en estructuras de datos como listas o arrays

• Construir funciones en tiempo de ejecución (closures) y devolverlas como valor de retorno de otra función

martes 12 de abril de 2011

Page 15: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Ejemplo: sumatorio

• La diferencia con Scheme es que Scala es un lenguaje tipeado y hay que definir el tipo de la función que se pasa como parámetro

• La función f que se pasa como primer parámetro de sum debe recibir un entero y devolver un entero

• Si pasamos otro tipo de función, Scala detecta el error de tipos

def square(x: Int): Int = x * x

def sum(f: Int => Int, a:Int, b:Int): Int = if (a>b) 0 else f(a) + sum(f, a+1, b)

martes 12 de abril de 2011

Page 16: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones anónimas

• Al igual que en Scheme con la forma especial lambda, en Scala podemos definir funciones anónimas creadas en tiempo de ejecución

• La función square anterior se podría definir de forma anónima como:

• Podemos definirla como parámetro de sum y no hace falta definir el tipo de las variables, porque Scala lo infiere a partir del tipo del primer parámetro:

(x: Int) => x * x

sum(x => x * x, a, b)

martes 12 de abril de 2011

Page 17: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Funciones anónimas

• Una notación más concisa utiliza subrayados como huecos (placeholders) de los parámetros de la función:

• Es equivalente a:

sum(_+2, a, b)

sum(x => x+2, a, b)

martes 12 de abril de 2011

Page 18: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Variables de tipo función

• Al igual que en Scheme, podemos asignar funciones a variables:

• Para asignar una función ya definida a una variable hay que utilizar la sintaxis de huecos (placeholders) para indicar al compilador que no tiene que aplicar la función:

def suma3(a: Int, b: Int, c: Int) = a + b + cval f = suma3 _ f(1,2,3) --> 6

val f = (s:String) => s + “adios”f(“hola”)

martes 12 de abril de 2011

Page 19: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Variables de tipo función

• Podemos almacenar funciones en listas, pero todas las funciones deben tener el mismo perfil:

def suma3(a: Int, b: Int, c: Int) = a + b + c def mult3(a: Int, b: Int, c: Int) = a * b * c

val listaFuncs = List(suma3 _, mult3 _)

val f = listaFuncs.headf(1,2,3)

martes 12 de abril de 2011

Page 20: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Variables de tipo función

• Ejemplo de función que toma una lista de funciones de un argumento y las aplica:

def aplicaLista (lista: List[(Int) => Int], x: Int): Int = if (lista.length == 1) lista.head(x) else lista.head(aplicaLista(lista.tail,x))

def mas5(x: Int) = x+5def por8(x: Int) = x*8val l = List(mas5 _, por8 _)aplicaLista(l, 10)

martes 12 de abril de 2011

Page 21: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Variables de tipo función

• Es posible utilizar la sintaxis de los huecos para proporcionar algunos de los argumentos y dejar libres otros.

• Con la siguiente expresión definimos una variable de tipo función de un argumento a partir de una función anterior

val g = suma3(1, _: Int, 10)

• Es posible utilizar la sintaxis de los huecos para proporcionar algunos de los argumentos y dejar libres otros.

• Con la siguiente expresión definimos una variable de tipo función de un argumento a partir de una función anterior

martes 12 de abril de 2011

Page 22: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Devolviendo funciones anónimas

• Las funciones pueden crearse y ser devueltas por otras funciones

• ¿Cómo declararías el tipo devuelto por la función makeSumador(Int)?

def makeSumador(k: Int) = (x: Int) => x + kval f = makeSumador(10)val g = makeSumador(100)f(4)g(4)

martes 12 de abril de 2011

Page 23: Tema 6: Programación funcional en Scala• A Scala Tutorial for Java programmers. Michel Schinz, Philipp Haller. November 2010. • The Scala Language Specification. Martin Odersky.

Closures

• Al igual que en Scheme, las funciones definidas en un ámbito mantienen el acceso a ese ámbito y pueden usar los valores allí definidos.

• Llamamos closure a estas funciones

• En el ejemplo siguiente, el ámbito en el que se crea la función devuelta contiene la variable i (el argumento de makeClosure) y la variable valor x declarada con el valor 5

def makeClosure(i : Int) : Int => Int = { val x = 5 (j : Int) => i + j + x}val returnedFuncion : Int => Int = makeClosure(10)println(returnedFuncion) //=> <function>println(returnedFunction(20)) //=> 35, porque 10 + 20 + 5 = 35

martes 12 de abril de 2011