2009/5/20 pointer <che...@gmail.com>:
> Now i'm thinking about some other issues. According to flapjax,
> traditional callbacks are avoided at most effort. Say, i have a small
> div block on page and i want to move its position by keyboard strokes,
> arrow directions. Now that I'm not encouraged to use callbacks, i have
> to find a way to identify what key user pressed. I have been reading
> tutorial and api doc but cannot find an effective way yet.
The key here is to think in terms of data dependencies, I think. What
events/behaviors does a position depend on?
Let's take a small counter example (pun intended). Say you have an
output field that displays current counter value, and a button to increase
that value. That button, when pressed, "creates" an event, and thus
generates a stream of events; every event is an object that holds
a function to increase it's argument by one:
b = function(x) { return x + 1; }, function(x) { return x + 1; }, ...
(I use this representation when I think of event streams [1])
How do we define a counter then? Quite easily: a counter is a *left fold*
over stream of button events (streams are somewhat analogous to singly
linked lists):
a = startsWith(collectE(b, 0, function(x,y) { return x(y); }), 0);
We turned 'a' into a behavior, so it always has a value. Initially, the value is
zero (it's called a 'seed'), but when an event arrives, we apply it to the seed
value, which gives us next seed. The process continues on.
There's more here. We can add another button, and it's event stream would
be defined as follows:
c = function(x) { return x - 1; }, ...
Since no user can press two buttons simultaneously, I think it's safe to combine
two event streams using mergeE:
x = mergeE(b,c)
We can supply this value to the collectE function, creating a counter with two
buttons. :) We can go further, by defining another button:
d = function(_) { return 0; }, ...
Guess what it does. :)
Hope this helps,
Artyom Shalkhakov.
[1] in Flapjax, that would be
clicksE('my-button').constantE(function(x) { return x + 1; })
This will let you create multiple moveE's (if you move that logic into
a function) that are initialized with different starting positions.
That will give turn this into a reusable abstraction: perhaps that's
what you're looking for?
Arjun