The flapjax paper makes a large point about the difficult of programming with side-effects. However I'm having trouble coming up with usable real-world patterns in flapjax that aren't side-effecting.
As one example, consider an animation loop. Changes arrive on an event stream. When the first one arrives, a draw should be scheduled for some time in the future (e.g. with requestAnimationFrame). Changes should then accumulate until the draw event fires, at which point all the accumulated changes should be drawn.
Is there a simple way to do this in flapjax? There seems to be a difficulty in expressing stateful things like "a draw event has been queued". The "world" pattern can be made to work, but then it's essentially the same as the imperative solution, and relies on side-effects.
Here's a solution using observer pattern:
function initialize(opts) {
var queued = false,
changes = {};
function dodraw() {
draw(changes);
queued = false;
changes = {};
}
opts.data_source.on('change', function (data) {
if (!queued) {
window.requestAnimationFrame(dodraw);
queued = true;
}
_.extend(changes, data);
});
}
And here's a flapjax solution using the "world" pattern:
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]]);
}
This is pretty much the same thing, only more obtuse. Nothing consumes the worldE stream. Draw events happen as a side-effect of constructing the stream.