Friday 29 December 2017

Varience in scala

Seriously I never remember which is which.

Covariance



Contravarience



Invariance


Friday 22 December 2017

Akka Persistence: From Untyped to typed

Vanilla Akka Persistence


Akka persistence involves three main concepts:

- Commands
- Events
- State

Consider the following two command objects:

case class WriteCommand(data: String)
case object PrintCommand

We are going to build an actor which responds to two sorts of commands 'Write!' and 'Print!'. When it receives a WriteCommand, the data in the command will be persisted and when it receives a PrintCommand it will print all the saved data to the console.

On receipt of a WriteCommand our actor will generate and persist a WriteEvent.

case class DataWriteEvent(data: String)

The actor will maintain an internal representation of the data it has persisted  ('state') . This is the data that will be printed to console on receipt of a PrintCommand.

The state has an update method which is called with a DataWriteEvent. The updated state is returned.

case class ExampleState(events: List[String] = Nil) {
  def updated(evt: DataWriteEvent): ExampleState = copy(evt.data :: events)
  def size: Int = events.length
  override def toString: String = events.reverse.toString
}

Wiring up the actor:

class ExamplePersistentActor extends PersistentActor {
  override def persistenceId = "example-id"
  var state = ExampleState()

  def updateState(event: DataWriteEvent): Unit = state = state.updated(event)

  def numberOfEvents: Int = state.size

  val receiveCommand: Receive = {
    case WriteCommand(data) ⇒
      persist(DataWriteEvent(s"$data-$numberOfEvents")) { event ⇒
        updateState(event)
        context.system.eventStream.publish(event)
      }
    case PrintCommand ⇒ println(state)
  }

  val receiveRecover: Receive = {
    case evt: DataWriteEvent ⇒ updateState(evt)
    case SnapshotOffer(_, snapshot: ExampleState) ⇒ state = snapshot
  }

}

And finally to run:

object Example extends App {
  val system = ActorSystem()
  val actor = system.actorOf(Props(new ExamplePersistentActor))
  actor ! WriteCommand("Ruby")
  actor ! PrintCommand
}

If I run it once I get the following:

List(Ruby-0)

And running it one more time:

List(Ruby-0, Ruby-1)

Moving on...


Receive is a function with a signature from Any => Unit which is pretty damn generic! Akka typed, the motivation for which is beyond the scope of this post, basically gives compile-time feedback on the correctness of your actor interactions. 

Sexy Types


This time we define a 'behaviour' in terms of Command, Event and State. This means that we need our 'Write!' and 'Print!' commands to share a type hierarchy: 

sealed trait TypedExampleCommand extends Serializable
case class TypedExampleWriteCommand(data: String) extends TypedExampleCommand
case object TypedExamplePrint extends TypedExampleCommand


Our event and state look pretty much the same as they did before:

case class TypedEvent(data: String)

case class TypedExampleState(events: List[String] = Nil) {
  def updated(evt: TypedEvent): TypedExampleState = copy(evt.data :: events)
  def size: Int = events.length
  override def toString: String = events.reverse.toString
}


 Our behaviour is defined with four parameters:

1. An id for the actor
2. An initial state
3. A function for converting commands to events (wrapped in 'Effects') and handling side effects
4. A function for updating the state given an event

object TypedExample {

  def behavior: Behavior[TypedExampleCommand] =
    PersistentActor
      .immutable[TypedExampleCommand, TypedEvent, TypedExampleState](
      persistenceId = "example-id", 
      initialState = new TypedExampleState,      
      commandHandler = PersistentActor.CommandHandler {
        (_, state, cmd) ⇒
          cmd match {
            case TypedExampleWriteCommand(data) =>
              Effect.persist(TypedEvent(s"$data ${state.size}"))
            case TypedExamplePrint =>
              println(state); Effect.none          
        }
      },     
      eventHandler = (state, event) ⇒ event match {
        case TypedEvent(_) => state.updated(event)
      }
    )
}

Now to run it:

object TypedExampleMain extends App {

  import akka.actor.typed.scaladsl.adapter._

  val system = akka.actor.ActorSystem("system")
  val actor = system.spawn(TypedExample.behavior, "example")
  actor ! TypedExampleWriteCommand("Hi Bella")
  actor ! TypedExamplePrint
}

Again running once gives:

List(Hi Bella 0)

And twice:

List(Hi Bella 0, Hi Bella 1)

Typed vs Untyped

Let's define a case object: 

case object FluffyKittenFace 

If we send a FluffyKittenFace message to our persistent actor then the message gets swallowed. The original code continues to work but nothing appears to happen. 

However if we try sending a FluffyKittenFace to our typed actor: 


Red squiggle of doom! 

We helpfully get a compile time error saying that our actor doesn't know what to do with all that fluff! 


FluffyKittenFace is going to have to find another actor to process her message, or become a TypedExampleCommand


Zee Cod:



https://github.com/polyglotpiglet/akka-typed-examples

Note that these examples are working against master rather than the release build. It should work from 2.5.9. 

Saturday 18 November 2017

NoVisibility.java example in Java Concurrency in Practice

I've been going through Java Concurrency in Practice and trying to reproduce the examples as I go through.

I found that when trying to illustrate the no visibility problem in chapter 3 the example in the code didn't work for me so I tweaked it a little bit:

Here is the test:



Then after running it for some time:

org.junit.ComparisonFailure:
Expected :0
Actual   :-1822446613

\o/

Wednesday 25 October 2017

Are you smarter than a pigeon?

I went to a talk on Monday at the Royal Institution entitled 'Are you smarter than a chimpanzee?' During this talk the lecturer referred to the Monty Hall problem and cited a study where university students played the game show and had to choose whether to stick or switch their choice of door.

Counterintuitively, switching improves your chances of winning from 1/3 to 2/3 but the university students tended to stick with their choice rather than switch, and therefore they didn't win very much. Part of this is because it's counterintuitive that switching would win and also because we humans are very loss averse. We prefer better to have chosen the wrong door and stick to it than to have chosen the winning door and give it up.

I wrote a little script which runs the Monty Hall problem and indeed around 66.6% of the time, switching will make you win.

The interesting thing from the talk is that apparently pigeons have played this game and unlike the university students, they learned very quickly that if they switch they improve their chances of winning, ie the birds outperformed the students.

How cool is that?



Scala with Cats: Answers to revision questions

I'm studying the 'Scala with Cats' book. I want the information to stick so I am applying a technique from 'Ultralearning&#...