FRP は、状態を明示的に管理せずにイベント ストリームを処理するものであると言う人もいます。たとえばこんな人。
http://www.slideshare.net/borgesleonardo/functional-reactive-programming-in-clojurescript
他の人は、非同期コールバックで行う必要があるように、副作用によって完全にプログラミングすることの難しさを指摘することによって、FRP を動機付けます。
http://cs.brown.edu/~sk/Publications/Papers/Published/mgbcgbk-flapjax/
しかし、FRP (flapjax) を使った実験では、同じ問題に直面し続けています: 副作用による明示的な場合を除き、状態を処理できないということです。
たとえば、アニメーション キューです。変更はイベント ストリームに到着します。最初の変更が到着したら、将来のある時点で (たとえば、window.requestAnimationFrame を使用して) 描画をキューに入れ、現在と将来の描画イベントの間の変更を蓄積するように手配する必要があります。描画イベントが発生したら、蓄積された変更を描画する必要があります。
これは約 6 行の命令型スタイルとオブザーバー パターンを使用したコードですが、これを FRP で表現する適切な方法が見つかりません。近づきそうな唯一の方法は、共有状態で関連するイベント ストリームを閉じ、状態を明示的に管理し、副作用を介してイベントをレンダリングすることです。命令型コールバックの改善にはほとんどなりません。
これをFRPでどう扱うか。
状態を閉じるためのflapjaxユーティリティは次のとおりです。
function worldE(init, handlers) {
var r = fj.receiverE();
fj.forEach(function(h) {
h[0].mapE(function (ev) {
r.sendEvent(init = h[1](init, ev));
});
}, handlers);
return r;
}
ここでは、アニメーション ループで使用されます。
function initialize(opts) {
var blitE = fj.receiverE();
function accumulate(state, data) {
if (!state.queued) {
window.requestAnimationFrame(blitE.sendEvent);
}
return {queued: true, changes: _.extend({}, state.changes, data)};
}
function dodraw(state, _) {
draw(state.changes);
return {queued: false, changes: {}};
}
worldE({queued: false, changes: {}},
[[opts.data_source, accumulate], [blitE, dodraw]]);
}
注意点: 同等のコールバック コードよりもサイズが大きく、読みにくく、保守性も劣ります。状態を明示的に管理する必要があります。そして、それは副作用を介して動作します。
FRPでこれを行うより良い方法はありますか? 別のパターンですか、それとも別のライブラリですか?