Transformando el futuro

Hace ya unas cuantas semanas estuvimos hablando sobre el tipo Future para crear llamadas asíncronas.
Vimos como trabajar con llamadas bloqueantes para obtener el valor del futuro. También utilizamos callbacks para obtener el resultado del futuro de forma asíncrona. Sin embargo se quedaron algunos puntos en el tintero. Me refiero a transformar los Future sin bloquear la ejecución.

Transformaciones de Futuros

Para transformar los futuros, al igual que con otros tipos básicos de Scala, se usa principalmente los métodos map y flatmap.

El método map

El método map nos permite cambiar el contenido de un futuro aplicando una función. Por ejemplo, si tenemos un método que nos permite obtener el primer millón de números primos, pero queremos transformarlo para que solo nos devuelva los cien primeros, podemos aplicar el método map de la siguiente manera:

def getFirstMillionOfPrimes(): Future[List[Int]] = ???

getFirstMillionOfPrimes().map(
  (list: List[Int]) => list.take(100)
)

De esta forma estamos transformando el interior del Futuro sin romper la asincronía.

pi2band2bi

El método flatMap

Por otro lado, el método flatMap nos permite aplicar una función al contenido del futuro, que devuelve un Futuro a su vez. Después, aplica una operación de flatten para convertir el Future[Future[A]] en un simple Future[A]. What the f…? Se entiende mejor con un ejemplo.

Imaginemos que queremos concatenar en una cadena de texto el primer millón de números primos. Para ello utilizamos un nuevo método:

def concatenate(l: List[Int]): Future[String] = ???

y ahora realizamos un flatMap

getFirstMillionOfPrimes().flatMap(
  (list: List[Int]) => concatenate(list)
) //Future[String]

¿Y como podemos componer hacer todo esto de una forma más sencilla?

Pues muy sencillo. ¡For comprehenssion al rescate! Aplicando un poco de syntactic sugar podemos tener un código mucho más legible.
Basta con hacer lo siguiente:

for {
  primes <- getFirstMillionOfPrimes()
  primesString <- concatenate(primes)
} yield primesString

De esta manera, no se aplicará la operación de concatenación hasta que no se hayan obtenido los números primos mediante el método getFirstMillionPrimes.
Esta permite guardar un cierto orden a la hora de hacer composición de llamadas asíncronas. Además, si la primera llamada asíncrona falla, no se efectuará la segunda.

Y esto es todo por hoy. Ahora ya sabes como cambiar el Futuro. Una lástima no poder cambiar el pasado 😦

doesnt-go-into-girls-shower

¡Hasta la próxima!

Deja un comentario