So far we have seen how we can move a ball on a separate thread/process and then reactivelly move it back where it was, see Closures and reactive programming.
Now, let's make it bounce. To bounce it, we'll change the direction of movement to up/down and we have to make the movement continuous, for a perpetuum mobile. So instead of just one function
moveItBack we'll need two functions
up which will chain each-other, so one is called at the end of the other, for a continuous movement (click Run below):
Simple enough? Remember that
c.animate launches an external process, it is not a simple recursive call, so we already have basically to chained reactive calls, that indirectly cause each-other: as you can see, the ball keeps moving!
Right... let's complicate it!
Now, in real-world physics, things are more interesting and we want our bouncing ball simulation to be more complete: we have to take care about changing the shape of the ball at the bottom: let's say it's a super-foam ball that will deform into an ellipse and then rebound back.
Our initial two phases of the movement were
up, so we will then have four phases of movement, to insert
Note that now we have a chain of closures that are called reactively:
drop-> squeeze -> bounce -> up -> drop and so on...
This is full on reactive programming now. Albeit circular, but each processing phase is invoked reactively at the end of the other. Each can be called on separate threads, but the closure mechanism takes care of any shared state (or not shared as the case may be).
You can call this a reactive flow, as each step starts the other. You can now see the direct analogy to a message passing system or actors, where there would be messages to start each phase.
Every call to
ball(c) creates such a flow instance and chains those closures together. They are not simply functions anymore since they capture the specific ball
c as well. You can easily test this by switching to "Play..." mode and fiddle with it, adding another blue ball a little to the right - they will move individually without interfering.
The abstraction in my mind is a processing pipeline that is now being sent events. Since this one is circular, it will kick itself with the same event, but you can easily see how it could also process any stream of events.
The one thing missing from our bouncing ball simulation is the time element and we may work on that at some point or... not!
The big attraction about functional programming is that it allows easy composition of fragments of code in the form of functions. So, the classical f o g o h, in essence, in a lazy functional language, builds a processing pipeline with three steps. This will be activated when the composition is actually sent something, at run time, when each step is executed and its result passed on to the next.
What we did above was to compose four functions but with a reactive flow rather than regular function composition, so each is called whenever the result of the previous one is not only available, but also later and on a different thread.
What does this tell us? Our example was a "void" and state was shared via the ball, but if our long-running computation (the animation) returned something, this would actually be the input for the next phase and so on.
Functional languages are really suitable for reactive programming! Same paradigms, same patterns, same solutions. How about a reactive monad? Or chew on this one for a bit: reactive combinators! Or another buzzword: reactive streams. All variations of the same idea: compose steps and bind them in different ways.