views:

9938

answers:

8

What does it mean in practice? What is non-reactive programming? Wikipedia has quite abstract description of it.

+7  A: 

OK, from background knowledge and from reading the Wikipedia page to which you pointed, it appears that reactive programming is something like dataflow computing but with specific external "stimuli" triggering a set of nodes to fire and perform their computations.

This is pretty well suited to UI design, for example, in which touching a user interface control (say, the volume control on a music playing app.) might need to update various display items and the actual volume of audio output. When you modify the volume (a slider, let's say) that would correspond to modifying the value associated with a node in a directed graph.

Various nodes having edges from that "volume value" node would be automatically triggered and any necessary computations and updates would naturally ripple through the application. The application "reacts" to the user stimulus. Functional reactive programming would just be the implementation of this idea in a functional language, or generally within a functional programming paradigm.

For more on "dataflow computing", search for those two words on wikipedia or using your favorite search engine. The general idea is this: the program is a directed graph of nodes, each performing some simple computation. These nodes are connected to each other by graph links that provide the outputs of some nodes to the inputs of others.

When a node fires or performs its calculation, the nodes connected to its outputs have their corresponding inputs "triggered" or "marked". Any node having all inputs triggered/marked/available automatically fires. The graph might be implicit or explicit depending on exactly how reactive programming is implemented.

Nodes can be looked at as firing in parallel, but often they are executed serially or with limited parallelism (e.g., there may be a few threads executing them). A famous example was the Manchester Machine, which (IIRC) used a tagged data architecture to schedule execution of nodes in the graph through one or more execution units. Dataflow computing is fairly well suited to situations in which triggering computations asynchronously giving rise to cascades of computations works better than trying to have execution be governed by a clock (or clocks).

Reactive programming imports this "cascade of execution" idea and seems to think of the program in a dataflow-like fashion but with the proviso that some of the nodes are hooked to the "outside world" and the cascades of execution are triggered when these sensory-like nodes change. Program execution would then look like something analogous to a complex reflex arc. The program may or may not be basically sessile between stimuli or may settle into a basically sessile state between stimuli.

"non-reactive" programming would be programming with a very different view of the flow of execution and relationship to external inputs. It's likely to be somewhat subjective, since people will likely be tempted to say anything that responds to external inputs "reacts" to them. But looking at the spirit of the thing, a program that polls an event queue at a fixed interval and dispatches any events found to functions (or threads) is less reactive (because it only attends to user input at a fixed interval). Again, it's the spirit of the thing here: one can imagine putting a polling implementation with a fast polling interval into a system at a very low level and program in a reactive fashion on top of it.

Edits and criticism welcomed.

Thomas Kammeyer
OK, there are some good answers up above now. Should I remove my post? If I see two or three people saying it adds nothing, I'll delete it unless its helpful count goes up. No point in leaving it here unless it adds something of value.
Thomas Kammeyer
you have mentioned data flow, so that adds some value IMHO.
Rainer Joswig
+5  A: 

This paper by Conal Elliott is a fairly good introduction. The corresponding library also works.

scvalex
+23  A: 

In pure functional programming, there are no side-effects. For many types of software (eg: anything with user interaction) side-effects are necessary at some level.

One way to get side-effect like behavior while still retaining a functional style is to use functional reactive programming. This is the combination of functional programming, and reactive programming. (The wikipedia article you linked to is about the latter.)

The basic idea behind reactive programming is that there are certain datatypes that represent a value "over time". Computations that involve these changing-over-time values will themselves have values that change over time.

For example, you could represent the mouse coordinates as a pair of integer-over-time values. Let's say we had something like (this is pseudo-code):

x = <mouse-x>;
y = <mouse-y>;

At any moment in time, x and y would have the coordinates of the mouse. Unlike non-reactive programming, we only need to make this assignment once, and the x and y variables will stay "up to date" automatically. This is why reactive programming and functional programming work so well together: reactive programming removes the need to mutate variables while still letting you do a lot of what you could accomplish with variable mutations.

If we then do some computations based on this, eg:

minX = x - 16;
minY = y - 16;
maxX = x + 16;
maxY = y + 16;

The resulting values will also be values that change over time. In this example, minX will always be 16 less than the x coordinate of the mouse pointer. With reactive-aware libraries you could then say something like:

d.drawRectangle(minX, minY, maxX, maxY);

and a 32x32 box will be draw around the mouse pointer and will track it wherever it moves.

Here is a pretty good paper on functional reactive programming.

Laurence Gonsalves
So reactive programming is a form of declarative programming then?
troelskn
d.drawRectangle(minX, minY, maxX, maxY);Aside: functional behavior fits nicely with functional graphics: `rectangle(minX, minY, maxX, maxY)`, which would be an expression rather than a statement.
Conal
Oops -- no markdown in comments?
Conal
> So reactive programming is a form of declarative programming then?*Functional* reactive programming is a form of functional programming, which is a form of declarative programming.
Conal
@Conal: Right, functional graphics make more sense. I'm not sure why I used an imperative style for the rectangle drawing bit.
Laurence Gonsalves
Very well-written answer. Simple and to-the-point, unlike the answer that was accepted.
musicfreak
+65  A: 

If you want to get a feel for FRP, you could start with the old Fran tutorial from 1998, which has animated illustrations. For papers, start with Functional Reactive Animation and then follow up on links on the publications link on my home page and the FRP link on the Haskell wiki.

Personally, I like to think about what FRP means, rather than how it might be implemented. So I don't describe FRP in representation/implementation terms as Thomas K does in another answer (graphs, nodes, edges, firing, execution, etc). There are many possible implementation styles, but no implementation says what FRP is.

I do resonate with Laurence G's simple description that FRP is about "datatypes that represent a value 'over time' ". Conventional imperative programming captures these dynamic values only indirectly, through state and mutations. The complete history (past, present, future) has no first class representation. Moreover, only discretely evolving values can be (indirectly) captured, since the imperative paradigm is temporally discrete. In contrast, FRP captures these evolving values directly and has no difficulty with continuously evolving values.

FRP is also unusual in that it is concurrent without running afoul of the theoretical & pragmatic rats' nest that plagues imperative concurrency. Semantically, FRP's concurrency is fine-grained, determinate, and continuous. (I'm talking about meaning, not implementation. An implementation may or may not involve concurrency or parallelism.) Semantic determinacy is very important for reasoning, both rigorous and informal. While concurrency adds enormous complexity to imperative programming, due to nondeterministic interleaving, it is effortless in FRP.

So, what is FRP? You could have invented it yourself. Start with these ideas:

  • Dynamic/evolving values (i.e., values "over time") are first class values in themselves. You can define them and combine them, pass them into & out of functions. I called these things "behaviors".
  • Behaviors are built up out of a few primitives, like constant (static) behaviors and time (like a clock), and then with sequential and parallel combination. n behaviors are combined by applying an n-ary function (on static values), "point-wise", i.e., continuously over time.
  • To account for discrete phenomena, have another type (family) of "events", each of which has a stream (finite or infinite) of occurrences. Each occurrence has an associated time and value.
  • To come up with the compositional vocabulary out of which all behaviors and events can be built, play with some examples. Keep deconstructing into pieces that are more general/simple.
  • So that you know you're on solid ground, give the whole model a composition foundation, using the technique of denotational semantics, which just means that (a) each type has a corresponding simple & precise mathematical type of "meanings", and (b) each primitive and operator has a simple & precise meaning as a function of the meanings of the constituents. Never, ever mix implementation considerations into your exploration process. If this description is gibberish to you, consult (a) Denotational design with type class morphisms, (b) Push-pull functional reactive programming (ignoring the implementation pieces in the latter), and (c) the Denotational Semantics Haskell wikibooks page. Beware that denotational semantics has two parts, from its two founders Christopher Strachey and Dana Scott: the easier & more useful Strachey part and the harder and less useful (for design) Scott part.

If you stick with these principles, I expect you'll get something more-or-less in the spirit of FRP.

Where did I get these principles? In software design, I always ask the same question: "what does it mean?". Denotational semantics gave me a precise framework for this question, and one that fits my aesthetics (unlike operational or axiomatic semantics, which leave me unsatisfied). So I asked myself what is behavior? I soon realized that the temporally discrete nature of imperative computation is an accommodation to a particular style of machine, rather than a natural description of behavior itself. The simplest precise description of behavior I can think of is simply "function of time", so that's my model. Delightfully, this model handles continuous, deterministic concurrency with ease and grace.

It's been quite a challenge to implement this model correctly and efficiently, but that's another story.

Conal
I have been aware of functional reactive programming. It seems related to my own research (in interactive statistical graphics) and I'm sure many of the ideas would be helpful for my work. However, I find it very difficult to get past the language - must I really learn about "denotational semantics" and "type class morphisms" to understand what's going on? A general audience introduction to the topic would be very useful.
hadley
+6  A: 

An easy way of reaching a first intuition about what it's like is to imagine your program is a spreadsheet and all of your variables are cells. If any of the cells in a spreadsheet change, any cells that refer to that cell change as well. It's just the same with FRP. Now imagine that some of the cells change on their own (or rather, are taken from the outside world): in a GUI situation, the position of the mouse would be a good example.

That necessarily misses out rather a lot. The metaphor breaks down pretty fast when you actually use a FRP system. For one, there are usually attempts to model discrete events as well (e.g. the mouse being clicked). I'm only putting this here to give you an idea what it's like.

+1  A: 

Paul Hudak's book, The Haskell School of Expression, is not only a fine introduction to Haskell, but it also spends a fair amount of time on FRP. If you're a beginner with FRP, I highly recommend it to give you a sense of how FRP works.

Curt Sampson
+1  A: 

FRP is great and very practical. You don't realize untill you try. If you like to try it in plain .Net (C#, VB) I suggest obtics

Maarten
A: 

Different kinds of semantics can be found at: http://symbolicanalysis.wordpress.com/2009/12/19/maximum-expressive-power-with-minimal-construction/. There is no mention about reactive programming except all program symbols calling other symbols activate their sub-functions in their automata and after finishing return their result if any. This is a simple call-return-phenomenon, which I regard as reactive programming, too.

Erkki