Scalera tips : var inmutable vs. val mutable

Supongamos que queremos definir una clase que tiene estado (una lista, por ejemplo).
Si siguiéramos el paradigma funcional puro, cada vez que modificáramos el estado de nuestra instancia, esta debería devolver una instancia nueva modificada:

class Foo(val state: List[Int]) {

  def mutate(n: Int): Foo =
    new Foo(state :+ n)

}

val initialFoo = new Foo(List())
assert(initialFoo.state==List())

val mutatedFoo = initialFoo.mutate(1)
assert(initialFoo.state==List())
assert(mutatedFoo.state==List(1))

…si te paras a pensarlo, es el comportamiento del método copy de una case class.

Pero pongámonos en el caso en que debemos integrarnos con una aplicación legacy y no podemos gestionar los cambios sobre nuestro Foo generando una nueva instancia.

En ese caso, el estado lo determina la lista interna, y no la instancia misma de Foo.

Una primera aproximación podría ser utilizar un val de tipo lista mutable (es threadsafe):

import scala.collection.mutable
class Foo {

  private val _state: mutable.ListBuffer[Int] = 
    ListBuffer()

  def mutate(n: Int): Unit = 
    _state += n

  def state: mutable.ListBuffer[Int] =
    _state

}

austinpowers

Y en la otra mano tendríamos la opción de usar un var inmutable (no es thread-safe):

class Foo {

  private var _state: List[Int] = 
    List()

  def mutate(n: Int): Unit = 
    synchronized(_state :+= n)

  def state: List[Int] = 
    synchronized(_state)

}

Fijaros que hemos tenido que hacer un synchronize para proteger el estado frente a accesos concurrentes.

¿Qué es mejor?

Si bien es cierto que la segunda opción genera mayor boilerplate, ocurre que con la primera podría darse el siguiente caso:

val foo = new Foo
assert(foo.state==mutable.ListBuffer())
val retrievedState = foo.state += 2
assert(foo.state==ListBuffer()) //ERROR!

Al devolver la lista, hemos roto el principio de transparencia referencial y perdemos el control de acceso sobre la lista.

Es probable que dependa del caso de uso de cada uno, pero en general, el enfoque funcional anima a generar nuevas copias de manera que se evitan potenciales efectos de lado.

Anuncios

3 thoughts on “Scalera tips : var inmutable vs. val mutable

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