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!

Anuncios

Scalera tips: Referential transparency

We have already talked in other posts about several details of pure functional programming and the importance of avoiding side effects wherever possible.

Should we investigate a bit further about it, we would likely run into the concept of referential transparency. Today it’s time to see what this concept is about.

giphy

Referential transparency is strongly linked to the substitution model. If we want to use Scala and exploit its full potential as a functional programming language, we must keep this concept in mind. Despite its weird name, it is pretty easy to understand. Referential transparency means that a function of type I => O ought to be replaceable by a value of type O, without that entailing any loss of functionality. This way, we can be sure that the function has no side effects.

Side effects: a function has no side effects if it only transforms the input arguments into output arguments and does nothing else. Connecting to a database, printing on screen, writing logs or modifying a variable outside the scope of the function are considered to be side effects.

Let’s see an example with code. In this example we are going to create a function that will allow us to book a hotel room. The function will update the hotel’s reservations list and will return an identifier for the user:

var reservations: List[Reservation] = List.empy[Reservation]

def reserveRoom(roomNumber: Int, from: String, to: String): Int = {
  val id = generateId()
  reservations = Reservation(roomNumber, from, to, id) :: reservations
  id
}

val myReservation: Int = reserveRoom(1, "1/8/16", "15/8/16")

In this case, we are modifying a list which is outside the scope of the function. This is a side effect. Therefore, if we performed a substitution by any value belonging to the function domain, we would lose functionality as nothing would be added to the reservations list:

var reservations: List[Reservation] = List.empy[Reservation]

val myReservation: Int = "1" //Result of reserveRoom method

reservations.isEmpty //true....where is my reservation???

How can referential transparency be achieved? A simple option would be to return both the new updated list and the reservation identifier:

var reservations: List[Reservation] = List.empy[Reservation]

def reserveRoom(
  roomNumber: Int,
  from: Date,
  to: Date
): (Int, List[Reservation]) = {
  val id = generateId()
  (id, Reservation(roomNumber, from, to, id) :: reservations)
}

val (myReservation, reservationsUpdated) = reserveRoom(1, "1/8/16", "15/8/16")
reservations = reservationsUpdated

This way, if we repeated the exercise of substituting by a value, we wouldn’t be losing any information at all. And that’s all for today! See you soon 😉

Scalera tips: Transparencia referencial

Ya hemos hablado en otros post sobre algunos detalles de la programación funcional pura o sobre la importancia de evitar los efectos de lado siempre que sea posible.

Si investigamos un poco en el tema, es posible que nos encontremos con el concepto de transparencia referencial. Hoy vamos a ver a qué se refiere este concepto.

giphy

La transparencia referencial está fuertemente ligada con el modelo de sustitución. Si queremos utilizar Scala utilizando toda su potencia como lenguaje de programación funcional, es necesario que tengamos en mente este concepto. A pesar de tener un nombre algo raruno, es bastante fácil de entender. La transparencia referencial indica que una función de tipo E => S debería poder ser sustituda por un valor de tipo S sin que eso supusiera una pérdida de funcionalidad. De esta forma, podemos estar seguros de que no la función no tiene efectos de lado.

Efectos de lado: una función no tiene efectos de lado si solamente transforma los argumentos de entrada en los de salida, y no realiza absolutamente nada más. Conectarse con una base de datos, imprimir por pantalla, crear logs o modificar una variable fuera del scope de la función, se consideran efectos de lado.

Vamos a ver un ejemplo con código. En este ejemplo vamos a crear una función que permita reservar una habitación de hotel. La función actualizará la lista de reservas del hotel y además devolverá un identificador para el usuario:

var reservations: List[Reservation] = List.empy[Reservation]

def reserveRoom(roomNumber: Int, from: String, to: String): Int = {
  val id = generateId()
  reservations = Reservation(roomNumber, from, to, id) :: reservations
  id
}

val myReservation: Int = reserveRoom(1, "1/8/16", "15/8/16")

En este caso, estamos modificando una lista que está fuera del ámbito de la función. Esto es un efecto de lado. Por tanto, si realizamos una sustitución por un valor cualquiera perteneciente al dominio de la función realmente estamos perdiendo funcionalidad porque ya no se está añadiendo nada a la lista de reservas:

var reservations: List[Reservation] = List.empy[Reservation]

val myReservation: Int = "1" //Result of reserveRoom method

reservations.isEmpty //true....where is my reservation???

¿Cómo podríamos cumplir la transparencia referencial? Una opción sencilla sería devolver, tanto una nueva lista actualizada, como el identificador de la reserva:

var reservations: List[Reservation] = List.empy[Reservation]

def reserveRoom(
  roomNumber: Int,
  from: Date,
  to: Date
): (Int, List[Reservation]) = {
  val id = generateId()
  (id, Reservation(roomNumber, from, to, id) :: reservations)
}

val (myReservation, reservationsUpdated) = reserveRoom(1, "1/8/16", "15/8/16")
reservations = reservationsUpdated

De esta manera, si repetimos el ejercicio de sustituir por un valor, no perdemos información ¡Y ya hemos acabado! Hasta la próxima 😉

Scalera tips: default parameters and overloading

It’s time today for a short post which hopefully will help some of you in discovering a new world. Today we are talking about the problems that may arise due to overloading when we have default parameters.

Let’s start defining the basic concepts:

– Overloading: …really?
– Default parameters: in Scala, it is possible to define default parameters in methods. These parameters can be obviated in the method call. With an example:

def getUri(host: String = "localhost", port: Int = 8080): String =
"$host:$port"

getUri("127.0.0.1", 8081) //"127.0.0.1:8081"
getUri(port = 8081) //"localhost:8081"
getUri("127.0.0.1") //"127.0.0.1:8080"
getUri() //"localhost:8080"

Great… and what’s the problem with it?

Let’s create the following trait:

trait A {
  def a(a: Int, p: Boolean = false)
  def a(b: Boolean = false)
}

We now compile and…

giphy2

error: in trait A, multiple overloaded alternatives of method a define default arguments.

However, if we take away the default parameter in the first function:

trait A {
  def a(a: Int, p: Boolean)
  def a(b: Boolean = false)
}

and we compile …..

giphy1

everything works.

What’s the reason for all this mess?

The problem is that the compiler uses default parameters to generate the names of some auxiliary functions that will help in dealing with the methods with default values (we shouldn’t forget that we are still in the JVM). Let’s see the example that is shown in the documentation:

def f(a: Int = 1, b: String)
// generates a method: def f$default$1 = 1
f(b = "3")
// transformed to: f(b = "3", a = f$default$1)

As can be observed, a new function is generated and the call to the original method is overloaded by making use of this function.

After this, we can say that in our messy example, the two auxiliary functions that are created will have this name:

def a$default$1 = false

and this is why a name conflict will arise.

In the second case, given that there is no default parameter in the first method, only one new function will be generated and thus, no conflict will appear.

And this is how our post ends 🙂

A small tour through ScalaRx (Part II)

A fortnight ago, we took a look at some of the functionalities that ScalaRx library provides us with. Today, we are going to end this small tour by getting on with Observables and all the advantages they offer.

Previously on Scalera…

In the previous post we saw how reactive variables work.  We learned how to declare them, modify them and create Rx structures that were modified when the reactive variables underwent a change.

The main idea of the post was that the objective of the ScalaRx library was to interpret reactive variables and their use as a flow that propagates changes whenever there is an update in any of the reactive variables. We can think of it as a butterfly effect.

Now, let’s see how we can make use of such changes with the Observable type.

giphy

The Observable type

By means of the Observable type, we will be able to perform certain actions when a reactive variable changes its value. For that purpose, we can create observations both of a Var and of Rx blocks. There are two constructors: trigger and foreach. With the first of them, we won’t have a reference to the new value. In order to get it, we would have to use a call to .now. On the other hand, with foreach we will have a reference to the new flow-propagated value.

Let’s create a pair of Observables which show on screen the new value. For that purpose, we will use the two versions of a constructor:

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.trigger {
  println(reactiveVar.now)
}
val o2 = reactiveVar.foreach { newValue =>
  println(newValue)
}

This example, once executed, will show on screen two “Hello World” given that the observables also act in the initialization of the reactive variable. If we want to miss the first change of the reactive variable, we can use triggerLater.

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.triggerLater {
  println(reactiveVar.now)
}

Finally, if we want to eliminate an Observable, we can use the kill instruction.

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.triggerLater {
 println(reactiveVar.now)
}
o1.kill()

By doing this, there won’t be any further reactions to changes in the reactive variable.

Conclusions

After these two posts, we can say that ScalaRx is based on data flows with several elements. As ScalaRx documentation rightly states, those elements can be seen as:

  • Var: root flow nodes that will provoke an avalanche with their changes.
  • Rx: intermediate flow nodes that will react to changes.
  • Observables: leaf flow nodes that will react to changes without propagating the flow further.

We can make use of this abstraction to create different types of applications or tools. For instance, we could have some dynamic configuration parameters (Var), being used by other variables (Rx) so that, if changes occur to any of them, a series of actions will be performed in order to be able to adapt to the new configuration:

import rx._
val host = Var(etcdHost)
val port = Var(etcdPort)
val databaseUri = Rx {host() + ":" + port()}
val obsDatabaseUri = databaseUri.triggerLater {
  connection.resetWith(<wbr>databaseUri.now())
}

This can be a common pattern to adapt to dynamic configuration parameters coming from ETCD or Consul, for instance.

And this is just an example. Obviously, we can do many more complex things with the flow started by changes in reactive variables. But we’ll leave that to future posts. Peace out!

Un pequeño paseo por ScalaRx: Parte II

Hace quince días estuvimos viendo muy por encima alguna de las funcionalidades que nos ofrecía la librería ScalaRx. Hoy vamos a acabar ese pequeño paseo dando un poco de caña a los Observables y todas las ventajas que nos ofrecen.

Anteriormente en Scalera …

En el post anterior  vimos como funcionaban las variables reactivas. Aprendimos como declararlas, como modificarlas y como crear estructuras Rx que fueran modificadas cuando las variables reactivas experimentaran un cambio.

La idea principal del post indicaba que el objetivo de la librería ScalaRx era interpretar las variables reactivas y su utilización como un flujo que propaga cambios cuando se produce alguna actualización en alguna de las variables reactivas. Podemos verlo como un efecto mariposa.

Ahora vamos a ver como podemos aprovecharnos de dichos cambios con el tipo Observable.

giphy

El tipo Observable

Mediante el tipo Observable podremos realizar determinadas acciones cuando una variable reactiva cambie de valor. Para ello podemos crear observaciones tanto de un Var como de bloques Rx. Existen dos constructores: mediante trigger o mediante foreach. Con el primero de ellos no tendremos una referencia al nuevo valor. Para obtenerlo debemos usar la llamada a .now. Por otro lado, con foreach tendremos una referencia al nuevo valor propagado en el flujo.

Vamos a crear un par de Observables que devuelvan por pantalla el nuevo valor. Para ello utilizaremos las dos versiones del constructor:

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.trigger {
  println(reactiveVar.now)
}
val o2 = reactiveVar.foreach { newValue =>
  println(newValue)
}

En este ejemplo, nada más ejecutarlo, mostrará por pantalla dos “Hello World” debido a que los observables actúan también en la inicialización de la variable reactiva. Si queremos saltarnos el primer cambio en la variable reactiva podemos usar triggerLater.

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.triggerLater {
  println(reactiveVar.now)
}

Por último, si queremos eliminar un Observable, podemos utilizar la instrucción kill.

import rx._
val reactiveVar = Var("Hello World")
val o1 = reactiveVar.triggerLater {
 println(reactiveVar.now)
}
o1.kill()

De esta manera, no se volverá a reaccionar a los cambios de la variable reactiva.

Conclusiones

Después de estos dos post, podemos comentar que ScalaRx se basa en flujos de datos en los que existen varios elementos. Como bien se comenta en la documentación de ScalaRx, dichos elementos se pueden ver como:

  • Var: inician los flujos y provocan una avalancha con sus cambios
  • Rx: nodos intermedios del flujo que reaccionaran a los cambios
  • Observables: nodos hoja del flujo que reaccionarán a los cambios sin propagar el flujo.

Podemos aprovecharnos de esta abstracción para crear distintos tipos de aplicaciones o herramientas. Por ejemplo, podríamos tener unos parámetros de configuración dinámicos (Var), que sean utilizados en otras variables (Rx) y que, si se producen cambios en ellos, necesitamos realizar una serie de acciones para adaptarnos a la nueva configuración:

import rx._
val host = Var(etcdHost)
val port = Var(etcdPort)
val databaseUri = Rx {host() + ":" + port()}
val obsDatabaseUri = databaseUri.triggerLater {
  connection.resetWith(databaseUri.now())
}

Este puede ser un patrón típico para adaptarnos a parámetros de configuración dinámica provenientes, por ejemplo, de ETCD o Consul.

Este es solo un ejemplo. Obviamente, podemos realizar cosas mucho más complejas con el flujo provocado por cambios en variables reactivas. Pero eso tocará verlo en futuros post. Agur de limón!

A small tour through ScalaRx (Part I)

Today’s post is dedicated to a library based on reactive functional programming: ScalaRx.

The main objective of this library is that, with the use of values (val), we are going to define an operations flow, which will change dynamically when any of the values changes. We call those values reactive variables.

To use the library, it is enough to add it as a dependency:

libraryDependencies += "com.lihaoyi" %%% "scalarx" % "0.3.0"

and to import rx:

import rx._

Reactive variables

Reactive variables will be the main elements we will be able to work with. To define them, the constructor Var will be used:

val reactiveVar = Var(0)

This way, we are defining a reactive value containing a 0. As can be observed, we can use val instead of var, even though the value will change. This is so because the state of the reactive variable is handled with ScalaRx.

Once we have a reactive variable, we can combine it with other static values or other reactive variables. So that our mastery and expertise can be noticed, we’ll perform a complex operation. We’ll be doing the sum of two reactive variables.

val sum1 = Var(1)
val sum2 = Var(4)
val result = Rx{ sum1() + sum2() }
result.now // Returns 5

In order to make reference to the use of the value of the variable in a reactive way, parenthesis are used. Furthermore, given that we want that the value of result changes as a function of the reactive values sum1 and sum2, we enclose it within an Rx block. If we want to evaluate result just after its definition, we’ll be able to do so with the now method. We will obviously be getting a wonderful 5.

Everything looks pretty simple right now. Let’s try to see how reactive changes do work. To do so, let’s change the value of the first summand. For that purpose, we will use again the parenthesis to make reference to the fact that we are changing the value contained in the reactive variable.

sum1() = 2

This update of the first summand will cause a reactive change that will affect the whole flow defined. In this case, it will only affect the result value.

result.now // Returns 6

This has been an extremely simple example. However, more complex flows could be created so that, when the value of a reactive variable is updated and following a ripple effect, a reaction is triggered at the rest of elements.

giphy

You may now be thinking “I already do this by replacing the reactive variables by our var friends and done”. Well, that’s true. However, Rx is intended to get notifications of the changes in the reactive variables and be able to respond to them (here you will find a more complete explanation). Observables are used for this purpose. We’ll have to wait to the second part of the post to get to them.

See you soon!