Questions
Question 1
I can't just do what I did above when I try to add int together.
Well, that’s actually the point. In reactive programming, you do not want to add two numbers in series together, instead you want to define a new number in terms of other numbers. Therefore, c = a + b , such c always equal to a + b , even if a or b changes: c is reactive with respect to a and b .
var a = new BehaviorSubject(3); var b = new BehaviorSubject(1); var c = Rx.Observable.combineLatest(a, b, function(vals) { return vals[0] + vals[1]; });
Question 2
I was wondering how to accurately implement the example given in the second highest ranking.
The simple answer is lists and higher order functions in haskell.
Answer that you do not want Functional-reactive programming goes against what you learned in imperative programming, and you will have to relearn how to do things if you want to do purely functional reactive programming. If you do not, you will end up creating all kinds of dependency tracking libraries like KnockoutJS , when you can do the same in a few hundred lines with something like RxJS-Splash if you used FRP to get you started. (note that Splash is based on Rx, which is reusable code, and Knockout is exclusively implementation-specific code).
FRP has the concept of events and time, while dependency tracking has the concept of values and changes. The functional reactive code was about the same as the imperative code. It is not "built on top of an imperative code." (yes, it still compiles to assembly ... not so), it’s important .
Example
Using Microsoft Reactive Extensions for JavaScript ( RxJS )
Keep in mind that Rx is now available in many languages, including native C ++ .
Direct port example
var moves = $(document).onAsObservable('mousemove') .map(function(e) { return { x: e.pageX, y: e.pageY }; }); var xs = moves.map(function(move) { return move.x; }); var ys = moves.map(function(move) { return move.y; }); var minXs = xs.map(function(x) { return x - 16; }); var minYs = ys.map(function(y) { return y - 16; }); var maxYs = xs.map(function(x) { return x + 16; }); var maxYs = ys.map(function(y) { return y + 16; }); var boundingRect = Rx.Observable.combineLatest(minXs, minYs, maxXs, maxYs) .map(function(vals) { var minX = vals[0]; var minY = vals[1]; var maxX = vals[2]; var maxY = vals[3]; return new Rectangle(minX, minY, maxX, maxY); });
Simplified port
Since a rectangle is defined only in terms of one dependent value (or event), you can simplify this to the following:
var boundingRect = $(document).onAsObservable('mousemove') .map(function(e) { var x = e.pageX; var y = e.pageY; return new Rectangle(x - 16, y - 16, x + 16, y + 16); });
Using
At this point, you can use it to compose other observable sequences (values that change over time).
var area = boundingRect.map(function(rect) { return rect.getSize(); });
Or subscribe to it directly.
boundingRect.subscribe(function (rect) {
But this is only when it changes!
What if we want to get the latest value as soon as we sign, instead of waiting for the rectangle to change again? Well, where is BehaviorSubject .
var rects = new Rx.BehaviorSubject(new Rectangle(-1, -1, 1, 1)); rects.subscribe(function(rect) { // this would happen twice in this example. // Once for the initial value (above), and once when it is changed later (below). console.log(rect); }); rects.onNext(new Rectangle(-1, -1, 1, 1));
But this is not the original, observed, and it is not very functional ...
Here's how to do the same with the original observable, using some built-in functions to change to Observable, to act like a BehaviorSubject ...
var rectsAndDefault = rects.startWith(new Rectangle()); // just give it an initial value rectsAndDefault.subscribe(function(rect) { console.log(rect); // happens once for the "startWith" rectangle, and then again for all subsequent changes })
Again, FRP is different. This is good, but it is a big task to learn. You will learn that you began to receive it when it begins to choke.