Functional Reactive Programming with Bacon.js

Lately I've been experimenting with Functional Reactive Programming, or FRP. There are several good libraries to use FRP with Javascript. I chose Bacon.js. I'm finding FRP to be very useful but hard to understand.

The way FRP is explained often leads to confusion. Most people know what the P is, and the F seems fairly understandable, but the R causes confusion. Examples usually talk about the difference between expressions and statements. Rather than c = a + b setting a value right now, it is an expression which defines that c is always a plus b. It defines a relationship. In another life I would have called this a binding expression. I suppose expressions get to the heart of what FRP is but it doesn't really explain why it's useful. Let me try another way.

FRP is this: working with streams of values that change over time.

Perhaps an example would help. Imagine moving a mouse over your browser. It produces a stream of x and y values. Rather than using a callback for every mouse move, we can work with the mouse events as a single object over time: an event stream. Suppose we want to know when the mouse moves past a line on the screen at 100px. In regular code we could do this:

$("body").on('mousemove', function(e) {
     if(e.pageX > 100) {
          console.log("we are over 100");
     }
};

With FRP we would create a stream based on mouse move, then filter it to only have X values over 100, like this:

$("body").toEventStream('mousemove')
     .filter(function(v) { return v > 100; })
     .onValue(function(v) {
          console.log("we are over 100: " + v);
     });

This is roughly the same amount of code so it doesn't seem like a big improvement. Trust me, it is. We have separated the action, printing a message, from the source of the stream and any filter operations. We can also add more operations to the stream if we want, and abstract the filters out further.

Talk to me about it on Twitter

Posted June 7th, 2013

Tagged: javascript frp