1

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でこれを行うより良い方法はありますか? 別のパターンですか、それとも別のライブラリですか?

4

3 に答える 3

1

私はFlapjaxに精通していませんが、ドキュメントを見るとcollectE、状態を蓄積するストリームを作成するために使用できます。receiverE次に、 と を使用して、animationFrame イベントの 2 番目のストリームを作成しますsendEvent

最後に、bacon.js sampledBy( https://github.com/baconjs/bacon.js/wiki/Diagrams#sampledby ) をエミュレートして、[animationFrame, state] タプルの 3 番目のストリームを作成します。

于 2013-09-03T18:25:40.037 に答える
0

ここでもう少しフラップジャックシュガー:sampledByを使用する代わりに、各フレームイベントで既に収集された変更配列のスナップショットを作成するsnapshotEを使用します。Google グループのトピックを確認してください。そのためのコードをいくつか書きました。

于 2013-10-23T09:43:52.417 に答える
0

FRP は完全に状態の管理に関するものです。しかし、それは時間のない状態を管理することです。これを行うには、ツリーまたはグラフ内で状態を維持する必要があります。これにより、コードの古いビットがランダムな時点で変更されるのを防ぎます。

FRP 状態では、親ノードが更新を起動したときにのみ更新されます。これが発生すると、イベントの値 (およびその他の親の値) を使用して、新しいノードの値が計算されます。

上記の blandw の答えは、collectE が必要なものであるため正しいです。

collectE では、親ノードが起動すると、このノードの以前の値が提供されます。これにより、変更のコレクションなど、任意の状態を保存できます。ただし、このコレクションは、親イベントが発生したときにのみ更新されます。

したがって、状態の変更を親の更新時に制限することで、多くの手間を省くことができます。これは、基本的な例ではわかりにくいです。大規模なプロジェクトに取り組んでいると、より顕著になります。

ただし、blandw の回答を更新するには、非 frp システムからイベントを取得する以外の理由で receiverE を使用しないでください。これは、FRP グラフの途中で発生することはなく、親を持たない最上位ノードとしてのみ発生します。それ以外での使用はFRPの趣旨に反します。

于 2015-08-26T04:45:47.797 に答える