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 😉

Anuncios

One thought on “Scalera tips: Transparencia referencial

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