Saltar a contenido

Clase 9: Colecciones II

Recursos

Expresiones for continuación

Que podemos hacer con las expresions for

Tener un lenguaje de consultas sobre conjuntos (base de datos)

Esto nos permite relacionar el paradigma funcional con el paradigma relacional

{for {
    l1 <- libros //generador
    l2 <- libros //generador
    if l1 != l2 //filtro
    a1 <- l1.autores //generador
    a2 <- l2.autores //generador
    if a1 == a2 //filtro
} yield a1 //withfilter con un flatMap
}.distinct 
//Autores que tienen al menos dos libros
// SELECT UNIQUE autores FROM libros l1 JOIN libros l2 WHERE l1.autores == l2.autores and l1 != l2 Flatmap vs map

flatMap vs Map

scala> val l1 = List(1,2,3)
val l1: List[Int] = List(1, 2, 3)

scala> val l2 = List(4,6,8)
val l2: List[Int] = List(4, 6, 8)

scala> l2 map (x => l1 map (y => (x,y)))
val res0: List[List[(Int, Int)]] = List(List((4,1), (4,2), (4,3)), List((6,1), (6,2), (6,3)), List((8,1), (8,2), (8,3)))

scala> l2 flatMap (x => l1 map (y => (x,y)))
val res1: List[(Int, Int)] = List((4,1), (4,2), (4,3), (6,1), (6,2), (6,3), (8,1), (8,2), (8,3))

withFilter vs filter

scala> l1
val res11: List[Int] = List(1, 2, 3)

scala> l1 filter (x => x%2 == 0)
val res12: List[Int] = List(2)

scala> l1 withFilter (x => x%2 == 0)
val res13: scala.collection.WithFilter[Int,[_]List[_]] = scala.collection.IterableOps$WithFilter@5a8149f6

scala> l1 withFilter (x => x%2 == 0) map (x => x)
val res14: List[Int] = List(2)

Maps

¿Que son?

Asociaciones de llave - valor, la llave debe ser única

Son coleccions inmutables

scala> val p:Map[Int,String] = Map(1->"perro", 2->"gato", 3->"lobo");
val p: Map[Int,String] = Map(1 -> perro, 2 -> gato, 3 -> lobo)

scala> p(1)
val res0: String = perro

scala> p(10)
java.util.NoSuchElementException: key not found: 10
  at scala.collection.immutable.Map$Map3.apply(Map.scala:417)
  ... 34 elided

scala> val p:Map[Int,String] = Map(1->"perro", 2->"gato", 3->"lobo") withDefaultValue "none";
val p: Map[Int,String] = Map(1 -> perro, 2 -> gato, 3 -> lobo)

scala> p(10)
val res2: String = none

//En caso de que hayan dos llaves iguales se reemplaza
scala> val p:Map[Int,String] = Map(1->"perro", 2->"gato", 3->"lobo", 1->"madre") withDefaultValue "none";
val p: Map[Int,String] = Map(1 -> madre, 2 -> gato, 3 -> lobo)
//Generar mapas
scala> l1
val res14: List[Int] = List(1, 2, 3)

scala> l2
val res15: List[String] = List(Hombre, Lobo, Gato)

scala> (l1 zip l2).toMap
val res16: scala.collection.immutable.Map[Int,String] = Map(1 -> Hombre, 2 -> Lobo, 3 -> Gato)

scala> (l1 zip l2)
val res17: List[(Int, String)] = List((1,Hombre), (2,Lobo), (3,Gato))

//Reemplazar un valor, genera un nuevo mapa
scala> m1 ++ Map(1 -> "Mujer")
val res21: scala.collection.immutable.Map[Int,String] = Map(1 -> Mujer, 2 -> Lobo, 3 -> Gato)

Evaluación perezosa

¿Que es?

Algunas colecciones son muy grandes y requiere muchos calculos (complejidad computacional elevada) y muchas veces no requerimos todos los datos

La evaluación perezosa nos ofrece la posibilidad de calcular hasta donde se requiere

La diferencia con la evaluación ansiosa, esta necesita calcular todos los elementos

scala> def enteros(n:Int=0):LazyList[Int] =
     | n #:: enteros(n+1)
def enteros(n: Int): LazyList[Int]

scala> val l = enteros()
val l: LazyList[Int] = LazyList(<not computed>)

scala> l(0)
val res22: Int = 0

scala> l
val res23: LazyList[Int] = LazyList(0, <not computed>)

scala> l(4)
val res24: Int = 4

scala> l
val res25: LazyList[Int] = LazyList(0, 1, 2, 3, 4, <not computed>)

scala> l(20)
val res3: Int = 20

scala> l
val res4: LazyList[Int] = LazyList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, <not computed>)

Conclusiones

La programación funcional provee un conjunto coherente de conceptos y técnicas de programación basados en:

• Programación de alto orden: Funciones que reciben o retornan funciones, currying esto nos permite tener mayor expresividad • Reconocimiento de patrones: Para agrupar condicionales y asignación • Colecciones inmutables: No pueden cambiar su valor • Ausencia de estado explícito: Los valores no cambian durante la ejecución • Estrategias de evaluación flexible: ansiosa, perezosa y por nombre

La programación funcional ofrece una caja de herramientas útil para todo programador y brinda una forma diferente de pensar para programar.

Resumen

La programación funcional combina conceptos como funciones de alto orden, colecciones inmutables, evaluación perezosa y patrones para mayor expresividad y eficiencia. Incluye técnicas como expresiones for, flatMap, mapas, reconocimiento de patrones y estrategias de evaluación flexible.