Event handling has turned over a new leaf. Instead of “subscribing” to “publishers”, you create a “stream” of events. When the event stream is implemented like a collection, it becomes a powerful abstraction that lets you create complicated event handling logic with relatively little effort.

The approach is called “Functional Reactive Programming”, or FRP for short. It’s basically a new angle on the observer pattern. When you start thinking about the Publisher of events as a Collection of events, you can transform that collection in the way you would expect from a functional-able language like Scala (map, filter, etc), and react to events using foreach. I’ll dive in with some examples “before” and “after” switching to FRP style.

//BEFORE
val pub = new Publisher[Int]

//AFTER
val events = new EventSource[Int]

Nothing special there.. how about listening to events?

//BEFORE
val sub = new Subscriber[Int] {
    def receive(event: Int) = { /* handle event */ }
}
sub.subscribeTo(pub)

//AFTER
for(event <- events) { /* handle event */ }

Okay, that seems to be a bit more concise. Now how about these “combinators”?

//BEFORE
val pub2 = new Publisher[Int]
val pubAdaptor = new Subscriber[Int] {
    def receive(event: Int) = {
        pub2.publish(event * 2)
    }
}
pubAdaptor.subscribeTo(pub)
val sub = new Subscriber[Int] {
    def receive(event: Int) = { /* handle event */ }
}
sub.subscribeTo(pub)

//AFTER
for(event <- events.map(_ * 2)) { /* handle event */ }

Wow! That certainly saved a lot of space. In case it’s not obvious, pub2 is supposed to be a publisher that fires any event from pub after multiplying it by 2. To get that, I had to set up an intermediate subscriber that would tell pub2 to fire the new event. In the “after” case, all I had to do was call map(_ * 2) on events, and all of that wiring was taken care of for me.

Assuming that the EventSource[T] class has all of the same combinators that you’d find on any other scala collection, you could presumably do something like…

val transformedEvents = events.takeWhile(_ != 5).filter(_ % 2 == 0).map(List(_ / 2))
val someOtherEvents = events2 collect {
    case "hello" => List(1,2,3)
    case "goodbye" => List(3,2,1)
}
val eitherEvent: transformedEvents.union(someOtherEvents)

There are a few things out there that already offer some of this functionality. C# has the “Reactive Extensions“ for LINQ, and there are a few open-source libraries floating around for scala like reactive-web. I took a stab at making my own implementation of this framework, which I call “Scala FRP.” It’s hosted on Github, and I’ve been making occasional additions to it since I got it to a stable state a couple weeks ago. The docs are pretty thorough, and you are free to look at the source code.

For further reading on the concept I described, Deprecating the Observer Pattern is where I first encountered it. The paper is a very difficult read, but is definitely worth at least looking at if you are interested in learning more.