質問
質問1
intを一緒に追加しようとしたときに、上記のことを行うことはできません。
さて、それが実際のポイントです。リアクティブ プログラミングでは、2 つの数値を強制的に加算するのではなく、他の数値に関して新しい数値を定義する必要があります。したがって、c = a + b
、そのようなc
ものは、またはが変更された場合でも、常にと等しくなります。 はおよびに関してリアクティブです。a + b
a
b
c
a
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];
});
質問2
2 番目に高い評価の回答に示されている例を正確にどのように実装するのか疑問に思っていました。
Haskell の最も単純な回答リストと高階関数。
望まない回答関数型リアクティブ プログラミングは、命令型プログラミングで学んだことすべてに反するものであり、純粋な関数型リアクティブ プログラミングを実行したい場合は、その方法を再学習する必要があります。そうしないと、KnockoutJSのようなあらゆる種類の依存関係追跡ライブラリを作成することになります。最初に FRP を使用した場合、RxJS-Splashのようなものを使用して数百行で同じことを実行できます。. (Splash は再利用可能なコードである Rx に基づいており、Knockout は純粋に実装固有のコードであることに注意してください)。
FRP にはイベントと時間の概念がありますが、依存関係追跡には値と変更の概念しかありません。機能的リアクティブ コードは、命令型コードと同じくらい長く使用されてきました。「命令型コードの上に構築された」ものではありません。(はい、それでもアセンブリにコンパイルされます...要点ではありません)、根本的に概念が異なります。
例
Microsoft の Reactive Extensions for JavaScript ( RxJS )の使用
Rx は現在、ネイティブC++を含む多くの言語で利用できることに注意してください。
例の直接ポート
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);
});
簡略化されたポート
四角形は 1 つの依存値 (またはイベント) に関してのみ定義されるため、これを次のように簡略化できます。
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);
});
それを使用する
その時点で、それを使用して他の観察可能なシーケンス (時間の経過とともに変化する値) を構成できます。
var area = boundingRect.map(function(rect) {
return rect.getSize();
});
または、直接購読してください。
boundingRect.subscribe(function (rect) {
// perform some action with the rect each time it changes.
console.log(rect);
});
しかし、それはそれが変わるときだけです!
四角形が再び変化するのを待つのではなく、サブスクライブするとすぐに最新の値が必要な場合はどうすればよいでしょうか? さて、そこにBehaviorSubject
s の出番です。
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));
しかし、それは元のオブザーバブルではなく、あまり機能的ではありません...
Observable を BehaviorSubject のような動作に変更する組み込み機能を使用して、元の Observable で同じことを行う方法を次に示します...
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
})
やはりFRPは違います。違いはありますが、学ぶのは大変な作業です。それがあなたの心を吹き飛ばし始めたとき、あなたはそれを手に入れ始めたことを知るでしょう.