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.