Scalera tip: Keep your actor’s state with no VAR at all!

It’s pretty well known that using VARs is, apart from unethical, the evil itself, some kind of hell, it make kitties die and many other stuff you might probably heard before and that could eventually be the cause of a painfull slowly dead.

The essence of functional programming is therefore the immutability: every time I mutate an element, I actually generate a new one.

What about Akka actors?

When we talk about actors, we can define them as stateful computation units that sequentially process a message queue by reacting(or not) to each of these messages.

It’s always been said that, in order to keep state within some actor’s logic, it was ok to use VARs:

It’s impossible that concurrency problems happen: it’s the actor itself and nobody else who access that var and will only process one message at a time.

But maybe, we could renounce to this premise if we look for some way to redefine the actor’s behavior based on a new state.

Mortal approach

If we follow the previously described philosophy, the very first (and more straight forward) approach for keeping some actor’s state would be pretty similar to the following:

class Foo extends Actor{
  var state: Int = 0
  override def receive = {
    case Increase => state += 1
  }
}

Every time an Increase arrives, we modify the state value by adding 1.
So easy so far, right?

Immutable approach

Nevertheless, we could define a receive function parameterized by certain state, so when a message arrives, this parameter is the state to take into account.

If the circumstances to mutate the state took place, we would just invoke the become method that would modify the actor’s behavior. In our case, that behavior mutation would consist on changing the state value.

If we use the previously defined example:

class Foo extends Actor{
  def receive(state: Int): Receive = {
    case Increase =>
      context.become(
        receive(state + 1),
        discardOld = true)
  }
  override def receive = receive(0)
}

we can notice that the function defined by receive is parameterized by some state argument. When some Increase message arrives, what we perform is an invocation to become for modifying the actor’s behavior, passing as an argument the new state to handle.

If we wanted some extra legibility, we could even get abstract from every updatabe-state actor:

trait SActor[State] extends Actor {
  val initialState: State
  def receive(state: State): Receive
  def update(state: State): Receive =
    context.become(
      receive(state),
      discardold = true)
  override def receive =
    receive(initialState)
}

this way, we just have to define the initial state of some actor, a new parameterized receive function and a new update function that takes care of performing the proper become call as explained before.
With all these in mind, we now have some cuter brand new Foo actor:

class Foo extends SActor[Int] {
  val initialState = 0
  def receive(state: Int): Receive = {
    case Increase => update(state +1)
  }
}

Potential hazardous issues

Please, do notice that in the featuring example, we’ve used a second argument for become: discardOld = true. This argument settles whether the new behavior should be stashed on the top of the older one, or ‘au contraire’ it should completely substitute the previous behavior.

Let’s suppose we used discardOld = false. If every single time a new Increase message arrived we had to stash a new behavior, we could obtain a wonderful overflow issue.

See you in the next tip.

Peace out 🙂

Scalera tip: Mantén estado en tu actor sin usar un solo VAR

Es de todos sabido que usar VARs es algo que, aparte de mal visto, está mal, es el infierno en vida, hace que mueran gatitos y muchas otras perlitas que probablemente ya habréis oído antes y que por poco os ha causado una muerte lenta y dolorosa en el cadalso.

La esencia en programación funcional es, por tanto, la inmutabilidad: cada vez que muto un elemento, genero uno nuevo.

What about Akka actors?

Cuando hablamos de actores, podemos definirlos como unidades con estado que procesan de manera secuencial una cola de mensajes, asociando (o no) a cada uno de estos mensajes una cierta lógica computacional.

Siempre se ha dicho que para mantener dicho estado dentro de la lógica de un actor, no pasaba nada si usabas un var:

Es imposible que hayan problemas de concurrencia: solo el propio actor tiene acceso a dicho VAR y procesará un solo mensaje al mismo tiempo.

Pero quizás podamos renunciar a esta premisa si buscamos una manera de redefinir el comportamiento del actor en base a un nuevo estado.

Mortal approach

Siguiendo la filosofía antes descrita, la primera (y más directa) aproximación para mantener el estado en un actor se parecería bastante a lo siguiente:

class Foo extends Actor{
  var state: Int = 0
  override def receive = {
    case Increase => state += 1
  }
}

Cada vez que llega un mensaje Increase, modificamos el valor de state, sumando 1.
Hasta aquí nada complicado, ¿no?

Immutable approach

Sin embargo, podríamos definir una función receive que estuviera parametrizada por un cierto estado, de manera que cuando llegue un mensaje, el estado a tener en cuenta sea este parámetro.

Si se diera la circunstancia de tener que actualizar el valor de dicho estado, bastaría con invocar al método become que modifica el comportamiento del actor. En nuestro caso, dicha modificación del comportamiento consistiría en cambiar el valor del estado.

Si usamos el mismo ejemplo que antes:

class Foo extends Actor{
  def receive(state: Int): Receive = {
    case Increase =>
      context.become(
        receive(state + 1),
        discardOld = true)
  }
  override def receive = receive(0)
}

vemos que la función que define el receive en base al estado recibe un parámetro denominado state. Cuando llega un mensaje de tipo Increase, lo que hacemos es invocar a become para modificar el comportamiento del actor, pasando como argumento el nuevo estado a tener en cuenta.

Si queremos mejorar un poco la legibilidad, podríamos incluso abstraer todo actor con estado actualizable:

trait SActor[State] extends Actor {
  val initialState: State
  def receive(state: State): Receive
  def update(state: State): Receive =
    context.become(
      receive(state),
      discardold = true)
  override def receive =
    receive(initialState)
}

de manera que se especifique el estado inicial del actor, una nueva función de receive que queda parametrizada por el nuevo estado a gestionar, y una nueva función de update que se encarga de realizar la llamada a become como antes explicábamos.
Con todo ello nos queda un nuevo actor Foo mucho más curioso:

class Foo extends SActor[Int] {
  val initialState = 0
  def receive(state: Int): Receive = {
    case Increase => update(state +1)
  }
}

Potential hazardous issues

Nótese que en el ejemplo de antes hemos pasado un segundo argumento: discardOld = true. Este argumento indica si el comportamiento nuevo debe apilarse sobre el anterior o si por el contrario debe sustituirlo por completo.

Supongamos que usáramos un discardOld = false. Si cada vez que llegase un mensaje de incremento, apilásemos un nuevo comportamiento, podríamos llegar a tener un problema de desbordamiento.

Hasta el próximo briconsejo.

Agur de limón 🙂

Scalera tips : var immutable vs. val mutable

Let’s suppose we want to define a class that has state (a list, e.g.).
If we followed the pure functional paradigm, each time we changed our instance’s state, this should return a new modified instance (with the new state).

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))

…if you just think about it, it’s a case class copy method behavior.

But let’s handle the situation where we have to integrate with some legacy application and we cannot manage changes over our Foo generating a new instance.

In this case, the state is determined by the internal list, and not the Foo instance itself.

A first approach could be using a val with a mutable list(which is thread-safe):

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

And, on the other hand, we could use a var with an immutable list (it’s not thread-safe):

class Foo {

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

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

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

}

Note that we’ve had to use a synchronize for protecting the state facing concurrent accesses.

Which is the best option?

Even it’s true that the second option generates more boilerplate, using the first one we could have the following situation:

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

When returning the mutable internal list, we’ve broken the referential transparency principle and we’ve lost the access control over the state.

It’s probably dependent on the use case, but in general, the functional approach aims to generate new modified copies so potential side effects are avoided.

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.

Vals and Vars *

Immutable vs mutable

One of the first lessons that the functional world gives away is that the values we declare (val) are immutable, i.e., they can only be given a value once and cannot be modified afterwards (we’ll see later that this statement has its nuances). Henceforth, if we declared:

val myNumber: Int = 2
myNumber = 3 //Compile-time error

We wouldn’t be able to change its value. This may seem odd at first, but variables (var), commonly used in other programming languages such as Java, are completely discouraged in Scala.

var myNumber: Int = 2
myNumber = 3
println(myNumber) //Prints out '3'

What’s the point in this? If we understand that any pure function is not allowed to maintain any state, then it seems obvious that variables can have no place in them. On the other hand, you might think: ‘Yeah, but the world is not functional: as an example, I/O is essential to configure the execution of a program’… You’re absolutely right. That’s why it is recommended that, if variables need to be used, checks are carried out to see if this is absolutely necessary and if so, they should be placed at the nearest point to the application entry.
For anything else, there’s masterVal

Nounces: Stateful objects.

We said earlier that if a variable is defined as val, its value cannot be modified. We also said that some nounces could be applied to this statement. Let’s assume that we have the following piece of code:

class Foo {
  private var initialized: boolean = false
  def initialize(): Unit = {
    initialized = true
  }
  def isInitialized(): Boolean = initialized
}

If we do now instantiate a Foo-type object

val immutableFoo = new Foo
immutableFoo.isInitialized() // false
immutableFoo = new Foo //Compile-time error

If we try to reassign its value, we’ll get a compile-time error (nothing new for now). But if we call its initialize method…

immutableFoo.isInitialzed() // false
immutableFoo.initialize()
immutableFoo.isInitialized() // true

…we will have modified its internal state. So, our Foo has become in what’s called a ‘Stateful object’: an object with state. Scala tries to refuse this behaviour but we should not forget that this is the normal thing to do in Java code. Given that one of the facilities of Scala is the integration with Java, the use of Java libraries and frameworks is common practice. Our recommendation is that this pattern is avoided in Scala implementations, but we have to be aware of its likely use in other tools that we might be integrating in our project.

The best of both worlds…

One of the main virtues of Scala (scalaz people would kill us for saying this) is the existence of var.

KqsQlDV

But had you not said before that var=crap? True. But it is precisely the fact that these kinds of expressions are not forbidden what eases the transition to Scala from other languages such as Java. A transition that might be less traumatic if, at first, the same old constructions are built but with Scala’s syntax for then, further on, adopting a proper functional style.

Vals and Vars

Inmutable vs mutable

Una de las primeras lecciones con las que nos congratula el mundo de lo funcional es que, los valores que declaramos (val), son inmutables, es decir, solo se asignan una vez y no pueden ser modificados (luego veremos que esto tiene matices). Por tanto, si declarásemos:

val myNumber: Int = 2
myNumber = 3 //Compile-time error

No podríamos modificar su valor. Puede resultar extraño al principio, pero las variables (var) de uso común en otros lenguajes de programación como Java, están totalmente desaconsejadas en Scala.

var myNumber: Int = 2
myNumber = 3
println(myNumber) //Prints out '3'

¿Qué sentido tiene esto? Si pensamos que toda función pura no debe mantener estado, es obvio que no tienen cabida las variables dentro de ellas. Por otra parte, podéis pensar: “Pero el mundo no es funcional: el I/O, por ejemplo, es necesario para configurar la ejecución de un programa”. …Pues tenéis toda la razón. Por eso se recomienda, en el caso de necesitar introducir una variable, comprobar si es realmente necesario, y en caso de que así sea, tratar de ponerlas en el punto más cercano a la entrada de la aplicación. Para todo lo demás….masterVal.

Matices: Stateful objects.

Decíamos antes que el hecho de que un valor se defina como val, implica que no puede modificarse. Del mismo modo también dijimos, que esto tiene matices. Supongamos el siguiente fragmento de código.

class Foo {
  private var initialized: boolean = false
  def initialize(): Unit = {
    initialized = true
  }
  def isInitialized(): Boolean = initialized
}

Si ahora instanciaramos un objeto de tipo Foo

val immutableFoo = new Foo
immutableFoo.isInitialized() // false
immutableFoo = new Foo //Compile-time error

Si intentamos reasignar el valor, obtendremos un error de compilación (hasta aquí nada nuevo). Pero si invocamos a su método initialize…

immutableFoo.isInitialzed() // false
immutableFoo.initialize()
immutableFoo.isInitialized() // true

…habremos modificado su estado interno. Nuestro Foo es lo que se denomina un ‘Stateful object’: un objeto con estado. En Scala se procura rehusar de este comportamiento, pero no olvidemos que esto es lo habitual en código proveniente de Java, y dado que una de las facilidades que aporta Scala es la integración con Java, es muy común utilizar librerías y frameworks escritos en Java. Por tanto, de cara a nuevos desarrollos en Scala, es preferible evitar este tipo de patrón, aun siendo conscientes que es probable que al integrar con otras herramientas, podemos encontrárnoslo.

Lo mejor de los dos mundos…

Una de las virtudes que tiene Scala (la gente de scalaz nos mata), es la existencia de los var. KqsQlDV

¿Pero no habías dicho antes que var=caca? Cierto. Pero precisamente el permitir este tipo de expresiones facilita la adopción de Scala a la gente que viene de otros lenguajes como Java. Una transición puede ser menos traumática si, en principio, usando la sintaxis de Scala, utilizas las mismas construcciones del lenguaje de donde provienes para, más adelante, acabar adoptando un estilo más funcional.