Link to wealthfront.com

Fork me on GitHub

Tuesday, April 9, 2013

Reactive.js: Functional Reactive Programming in Javascript


Reactive.js is a pure Javascript library inspired by Functional Reactive Programming. If you've ever used Excel or another spreadsheet program, you've already done something like FRP.

Reactive.js aims to bring FRP to Javascript by augmenting Javascript functions, allowing you to declare data flows in your code by representing your values as reactive functions that depend on one and other. Complicated UIs, data visualizations, and systems of calculations are examples of just a few problems that can be simplified by using reactive programming.

Reactive.js is already being used in production on Wealthfront.com, where it's helping us gracefully manage the interconnection of portfolio model calculations, visualizations and UI elements. Check out a sample plan to see what I mean (it's pretty neat).

If you've never heard of FRP before I'll step you through some basics and show you how Javascript (and Reactive.js) enter the picture. You can also grab Reactive.js on github right now, the README provides a walkthrough and introduces the API if you'd prefer to jump right in.

Reactive Programming in 60 seconds


In Reactive programming it's easier to think of our variables as expressions, not as assignments. In order to understand the difference, consider the statement "a = b + c".

There are two ways to look at this. One is the way we are used to, "a is assigned to the sum of b and c, at the instant this is interpreted", which is what we'd expect in Javascript or any other imperative language.

But we could also read it as "a represents the sum of b and c, at any point in time." This interpretation is not really so strange, that's exactly how we would expect things to work in a spreadsheet. If we had a spreadsheet cell containing the expression "=B+C", the value in that cell would change as the cells B and C change, wouldn't it?

Reactive programming means we describe our program using the second interpretation. We don't assign variables, we express them, and they don't represent discrete values, they represent a value that changes over time.

Reactive Programming in Javascript

Obviously Javascript is not a reactive language, but there are advantages to being able to express ourselves reactively. Reactive programming can be immensely useful in describing systems of equations, complicated UIs, and data visualizations to name a few.

So let's reexamine our earlier statement about reactive programming, then we'll see how Javascript fits into the picture (and how Reactive.js fits into Javascript).
"We don't assign variables, we express them..."
In Javascript, a = b + c assigns a value. For us to accomplish our goal, however, we need to describe what a represents using an expression (like =B+C in a spreadsheet). Javascript does have expressions, they're called functions! So in reactive programming a given value, like a in a = b + c is expressed as a function:
    var a = function (b,c) { return b + c } // a = b + c
This brings us to our first conclusion.

Conclusion 1: Our variables are expressions, so our variables are functions.

Now lets consider the rest of the sentence:
"…and they don't represent discrete values, they represent a value that changes over time"
When you write =B+C in a spreadsheet, your spreadsheet program notes that your cell is relying on the values of B and C. It starts to assemble a dependency graph internally that it can use to keep track of changes. It traverses that graph when B or C change, updating A in the process. Most importantly, we don't have to write a "calculate all" function because the spreadsheet program handles that for us.
Unfortunately Javascript won't magically track dependencies, so it's not enough to describe our variables as expressions, we also need to tell our expressions what they depend on. Only then can they be smart enough to update each other automatically.

Conclusion 2: We have to tell our expressions what they depend on.

When we combine our two conclusions, we arrive at the following:
Our variables are expressions, so our variables are functions. And we have to tell our expressions what they depend on, so that means we have to tell our functions what they depend on.
Fortunately for you, Reactive.js does just that.

Using Reactive.js

At its core, Reactive.js is just a single method, $R(). $R() accepts a function and returns you an augmented version of that function that is meant to represent a value in your program. How is it augmented exactly? "Reactive functions" gain a new method called .bindTo(). bindTo() accepts one or more reactive functions, and binds them to your function's arguments via partial application.
Don't worry about $R.state yet, it just returns a reactive function that gets and sets internal state (handy for literal values) — the docs explain it in more detail.
    //A = B + C
    var reactiveA = $R(function (b, c) { return b + c });
    var reactiveB = $R.state(2);
    var reactiveC = $R.state(1);
    reactiveA.bindTo(reactiveB, reactiveC);

    reactiveA();   //-> 3
    reactiveB(5);  //Set reactiveB to 5
    reactiveC(10); //Set reactiveC to 10
    reactiveA();   //-> 15
That's it. As you can see, Reactive.js asks you to express values as functions and gives you the tools you need to tell those functions how they depend on each other. In the example above, any time reactiveA or reactiveB change, reactiveC will change too. reactiveC isn't assigned a+b, it represents a+b at any moment in time.

An example with time

Since we talk about variables representing a value that changes over time, let's actually create variables that depend on, well, a value that changes over time.


Reactive.js is minimal

Reactive.js seeks to be as minimal and unobtrusive as possible. Because it operates on, and returns, normal Javascript functions, it's very easy to integrate into existing code. If you start writing "reactive" code, any existing function can be integrated as a dependency by creating a reactive version of it with $R().

The future

Reactive.js is new, but improving every day. Our newest adventure is defining our d3 visualizations declaratively, using Reactive.js, instead of the imperative pattern we're used to. We're able to describe how data might flow into a visualization, informing things like the x and y scales, and updating the relevant SVG. In the process we do away with our classic "render-all" function, instead trusting Reactive.js to update only the components of the visualization that need changes when the data is modified.

Stay tuned in the weeks to come as we show other ways Reactive.js can integrate into your code