Skip to content

Instantly share code, notes, and snippets.

@javierfernandes
Created May 11, 2019 14:33
Show Gist options
  • Select an option

  • Save javierfernandes/ebeab2842a2447a3e438f95c5d79001b to your computer and use it in GitHub Desktop.

Select an option

Save javierfernandes/ebeab2842a2447a3e438f95c5d79001b to your computer and use it in GitHub Desktop.
O3 - FP - Pociones - En clase (2019-c1)
package ar.edu.unq.o3
object Hogwarts {
// definiciones de tipos
type Persona = (String, Niveles)
type Niveles = (Int, Int, Int)
type Efecto = Niveles => Niveles
// permite acceder a los elementos de la tupla Niveles mediante un mensaje con nombre
// en lugar de usar ._1, ._2 y ._3
implicit class NivelesWrapper(n: Niveles) {
def suerte = n._1
def convencimiento = n._2
def fuerza = n._3
}
def niveles(p: Persona): Niveles = p._2
}
object Efectos {
import ar.edu.unq.o3.Hogwarts._
//
// primera versión de duplica y alMenos7 usando mapNiveles
//
def mapNiveles: (Int => Int) => Efecto = fn => n => {
(fn(n._1), fn(n._2), fn(n._3))
}
def duplicaV1 = mapNiveles(_ * 2)
def alMenos7V1 = mapNiveles(_.max(7))
//
// segunda versión usando composición de funciones (andThen)
// claramente es mejor la primera versión. Lo hicimos como excusa para trabajar más con funciones
// y probar la composición
//
// necesitamos funciones auxiliares
def toList = (n: Niveles) => List(n._1, n._2, n._3)
def fromList = (l: List[Int]) => (l(0), l(1), l(2))
// definimos el map() de listas de Int como una función de orden superior y aplicación parcial
// usamos gruppos de parámetros para poder primero llamara con la operación de mapeo y luego que
// otra función la aplique efectivamente con la lista.
// En nuesto caso el andThen se va a encargar de aplicarle la lista, como parte de la composición
// o "linea/pipeline" de ejecución del "duplica"
def map(fn: (Int) => Int)(l:List[Int]) = l.map(fn)
//
// Esto se podría haber definido de otras formas sin usar "grupop de parametros" de scala
//
// map2: un solo grupo de parametros. El que la use la va a tener que aplicar parcialmente, así
// toList.andThen(map2( a => a *2, _ )).andThen(fromList)
def map2(fn: (Int) => Int, l: List[Int]) = l.map(fn)
// map2: función de orden superior. El map ahora retorna una nueva función. Así que no hace falta
// aplicarla parcialmente. Es una función "creadora" que crea otra función
// esta la usaríamos así, igual que la "map" original
// toList.andThen(map3(a => a * 2)).andThen(fromList)
def map3(fn: (Int) => Int) = (l: List[Int]) => l.map(fn) // vemos que retorna una arrow function
// ahora sí, podemos definir los efectos
// Efecto duplica definido componiendo funciones
def duplica = toList
.andThen(map(PorDos))
.andThen(fromList)
def alMenos7 = toList.andThen(map(_.max(7))).andThen(fromList)
// Efecto definido como un objeto que extiende a la clase Funcion (Int) => Int
object PorDos extends Function1[Int, Int] {
override def apply(e: Int): Int = e * 2
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment