An introduction to functional reactive programming Portal

This is an interpretation of a talk from mdevcon 2014. It is heavily inspired by What Screens Want by Frank Chimero and the case studies at Teehan+Lax.

In the beginner’s mind there are many possibilities,
in the expert's mind there are few.

— Shunryu Suzuki

Long ago, when computer programming first came to be, machines had to be programmed quite manually. If the technician entered the correct sequence of machine codes in the correct order, then the resulting program behavior would satisfy the business requirements.

Then we invented a higher-level programming language: C. And once more, if the programmer wrote the correct sequence of instructions in the correct order, then the resulting program behavior would satisfy the business requirements.

The 1980's: A Revolution in Software

The 1980's saw the invention of a new way to write computer programs: object-oriented programming. The programmer would write code that manipulated the data belonging to re-usable "objects", and if the programmer wrote the correct instructions in the correct order, then the resulting program behavior would satisfy the business requirements.

After that, things got pretty boring.

Most modern programming today is basically imperative, meaning it models the traditional fetch-execute cycle of a CPU. Perform an instruction, fetch the next one. Perform that one, and so on. For decades, programmers have had to mould their brains to fit the paradigm of the CPU.

Imperative Programming is Dangerous

When we rely on hoping that the behavior that emerges from a program is correct, and that reliance is based on nothing more than a programmer's correctness, then we can easily find ourselves in a sticky situation. We can try and mitigate the costs of imperative programming with things like unit tests or integration tests, but why mitigate the costs when there's a better way?

Instead of telling a computer how to do its job, why don't we just tell it what its job is and let it figure the rest out? The bottom line is imperative programming is error-prone and relies too heavily on the infallibility of the programmer.

There is a Better Way

Instead of imperative programming, we can use a new paradigm to structure our code.

Functional Reactive Programming

Functional. Reactive. Programming. What on Earth is that?

Well, we know to some degree what functional programming is. Functions don't have side-effects; there's no mutable state. It's a difficult way to program since the real world is mutable. Modelling things like user input becomes a nightmare.

Reactive programming? What's that? Well, the best way to describe reactive programming is to think of a spreadsheet. Imagine three cells, A, B, and C. A is defined as the sum of B and C. Whenever B or C changes, A reacts to update itself. That's reactive programming: changes propagate throughout a system automatically.

Functional reactive programming is just a combination of functional and reactive paradigms. We model user input as a function that changes over time, abstracting away the idea of mutable state.

Functional reactive programming is the peanut butter and chocolate of programming paradigms.

At the core of functional reactive programming is a signal. A signal is a rather abstract concept, and it's easier to describe what a signal does rather than what it is. A signal simply sends values over time. It sends values until it either completes, or errors out, at which point it stops sending values forever. A signal either completes or errors out, but not both.

Signals have no sense of a "current value" or "past values" or "future values", they are very simple. They just send values over time. Signals become useful when they're subscribed to or used with bindings, both cases of which we'll cover shortly. For now, it's important to understand that a signal can be transformed.

If I have a signal that sends numbers, and I want it to send strings instead, I can easily transform that signal with a map. A map is an operator that takes in a signal as a receiver, performs some operation on the values sent over that signal, and generates a new signal with the new, mapped values.

A signal can be subscribed to in order to perform side-effects. A good example would be the signal emitted by a button when it's pressed; we can subscribe to that signal in order to perform side effects. A signal can also be bound to a property. For example, a signal that sends the location of a gesture recognizer can be mapped to a color and bound to the background color of a view. Then, when the user changes their tap position, the view changes color.

Both of these examples, of subscription and binding, demonstrate that we can create a set up at the beginning of an application runtime and tell the code what to do without telling it how to do it. This is the value of functional reactive programming.

Another core concept in functional reactive programming is that of derived state. State is OK in ReactiveCocoa, as long as its bound to a signal. This derived state means that you never explicitly set the value of a bound property, but rather rely on signal transformations to derive that state for you.

ReactiveCocoa is an implementation of functional reactive programming that is built on top of the Cocoa and CocoaTouch libraries that you're already familiar with.

Getting Started is Easy

There are many resources available for you to explore the world of ReactiveCocoa. Check out the ReactiveCocoa README for a list of resources.