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 😉

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s