What is Reactive Programming?

I enjoyed reading this question on Stack Overflow: What is (functional) reactive programming? I thought I'd take a stab at an explanation of what reactive programming means to me. Let me take you to the future.

The year is 2051, and our team of code anthropologists discovered some ancient script in the long-abandoned ruins of a decaying open source project repository. With some deciphering, we discover the the script is written in a primitive dialect of P#, the dominant language of the year 2051. It reads:

var a = 10;
var b = a + 1;
a = 11;
b = a + 1;

Through careful analysis of the script, we eventually decipher this to be an ancient parable. It tells the story of two brothers. a is the first born, proud and independent. b is the younger of the two, but it is dependent; it needs a. But the relationship is short lived. Once the second line is executed, and b grows up, the relationship between the adventurers ends - b is no longer dependent on a. When a changes, b does not. a must attempt to re-establish the once-lost relationship, but even that does not last.

We can relate to this as if it were the code version of Cats in the Cradle. First there is a, and b who needs a. But by the third line, b has grown up, and has no time for a. It is only when a calls that the two are momentarily re-connected, but even that is only fleeting.

Thanks to these cave paintings, we can draw the conclusion that the primitive compilers weren't smart enough to figure out that the destinies of these two proud brothers were intertwined. It seems that ancient programmers had to continually re-establish the relationship, or risk data being out of sync. As modern day code anthropologists, it's hard to imagine how it might have felt to write code like this.

In the year 2051, reactive programming is the norm. Language creators discovered the destiny operator decades ago, and the old ways were quickly forgotten. For example, in P#, we can write:

var a = 10;
var b <= a + 1;
a = 20;
Assert.AreEqual(21, b);

As you can see, the statement establishes b and a as having intertwined destinies, which are unbroken and forever. They are bound. The relationship between them isn't implicit, an idea that only exists in the mind of the programmers; it's explicit, a part of the language, and it exists for all time.

Although the destiny operator is wide spread, the way it works is a closely guarded secret. Some say that when the compiler encounters code that changes a, it inserts the corresponding change for b, such that they are always in sync. Others say that a, instead of being a lowly 4-byte integer, is ascended into a higher plane of existence. It becomes an observable, an object whose changes reverberate throughout the software at runtime, with the aid of event handlers created by the compiler. Old wives tales even tell of a great timer that constantly ticks, re-aligning all the variables after every change.

Nevertheless, through understanding the parable of the dependent brothers and getting a glimpse into the ways of ancient programmers, we can be even more thankful for the destiny operator and reactive programming. Instead of slaving over repetitive code and dealing with bugs, modern programmers can express relationships that last forever.

NB: P# is just the nickname for Microsoft Visual C#++Basic.NET on Rails, created by Paul Stovell in the year 2021

A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy Octopus Deploy, an automated deployment tool for .NET applications.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

Jeremy Gray
Jeremy Gray
04 Jan 2010

Modulo 'a = 20;', when reading your sample my mind flashed back to my CS days and Prolog was the first thing that came to mind. Are you sure that P# doesn't refer to Prolog? ;)


04 Jan 2010

You know, functions work well too... b = function() { return a + 1 }, and they are well understood already.

tom
tom
04 Jan 2010

I must indeed with above - this is what functions are for, and devising some kind of other name for this is weird when you can call functions without parens in ruby, etc., eliminating any ugliness.

04 Jan 2010

In the future there won't be anything like the text "var" to indicate that it's a variable...

Carl Scarlett
Carl Scarlett
05 Jan 2010

For me, the exciting thing about Rx is the ability to create listeners for my own events (e.g., if I'm interested in the keystrokes "a" followed by "b" followed by "c" I can create an event that notifies me when this occurs). The observable pattern has huge benefits for code simplification.

In practice though, I think it'll be years before we start seeing Rx used in anger (though that statement is probably influenced by the devlopment culture here in Perth, Australia).

anon
anon
05 Jan 2010

hmmm, not very new at all. In good old C:

int a = 10;
#define b (a+1)
a = 11;
assert(21 == b);

The compiler, in fact, is likely doing something like C macros, or else functions under the hood. The compiler/VM "automatically" changing N variables, which are a function of each other, is absolutely stupid. Sorry.

05 Jan 2010

Paul - I really enjoyed reading this - nice work! Shame that such a light-hearted post seems to attract a few overly serious, bordering on negative comments. I like the sound of the "desinty operator" - do you know where I can pre-order a copy of P# :-)

Shrikster
Shrikster
06 Jan 2010

Isn't that the reason we use getters and setters ?

06 Jan 2010

nice post........enjoy reading...

07 Jan 2010

Nice story Paul, but as everyone pointed, there are many ways of solving it now....

Are u going to release a preview of p# this year? Can't wait until 2021

Luis
Luis
07 Jan 2010

I a lot of people here are missing the point. It's not a matter of whether there is already a way to do it, it's about having a different way of doing it, possibly one that captures the intent better with less code.

I love that about C#, for example C# has properties, which does nothing a function doesn't already do.

string getName() {} void setName(string name) {}

But the syntax is more readable and requires less code:

string Name { get {} set {} }

Using it looks nicer too.

setName("Joe"); - vs - Name = "Joe";

Same thing with lambda expressions vs. delegates.

I'm not saying this reactive feature does it for me, perhaps a more contextual example of a problem that it solves would be in order, but the point is it's not about theres already being a way of doing it, its a question of whether it's a better way.

10 Jan 2010

I agree we're missing the point and I also think there's a lot of room for improvement. I think it's nice that we could think more naturally of it instead of thinking in a "lamda function" or Property (which would've a different scope) we just think of setting up a "derived" value. So although lambdas and properties are current solutions, there's room for something like the "Destiny Operator".

A quick way of getting there would be to have better type inference for lamdas and anonymous delegates and to be able to evaluate them without braces (a'la Ruby)

var a = 10; var b = ()=> a + 1; // You still need to be explicit about the type. In C# a = 20; Assert.AreEqual(21, b); // You would need to use () to evaluate it.

I'm sure other languages make a better job on this respect and we know that C# will slowly introduce new features to simplify common tasks.

26 Oct 2010

A quick way of getting there would be to have better type inference for lamdas and anonymous delegates and to be able to evaluate them without braces