Conquering ReactiveSwift: Introduction
“Reactive Programming has a steep learning curve.”
I kept hearing this while I was learning Functional Reactive Programming (FRP). Coming from a background of imperative programming, I struggled to grasp various concepts of FRP. At its most basic, the benefit of FRP is that it allows you to model time. But this can be hard to get your head around. To help you get over the learning hump, I’m sharing my learning experiences in this “Conquering ReactiveSwift” series. My aim is to provide a step-by-step guide for beginners to learn ReactiveSwift.
This is the first article in the series. It gives an introduction to Functional Reactive Programming and explains how it is different from imperative programming.
Imperative vs Functional Reactive
To understand the difference between these programming paradigms, let us take an example. Suppose we want to implement a user interface having one UILabel (let’s call it label
) and one UITextView (let’s call it textView
), where the UILabel reflects the text entered in the UITextView. To achieve this behaviour, we write this:
func textViewDidChange(_ textView: UITextView) {
label.text = textView.text
}
The above code works just fine. We have been doing this forever. So what is the problem? Let’s investigate. Consider the statement, designed to update the text of label:
label.text = textView.text
It is an assignment statement.
What does this mean? This means the label.text
becomes equal to textView.text
at the moment of the assignment. This statement does not encapsulate any information about the state of label.text
before or after the point of the assignment. In other words, the statement label.text is equal to textView.text
doesn’t necessarily hold true once we introduce the notion of time to the model.
Therefore, we need to encapsulate this statement inside the delegate method textViewDidChange
so that the state of the label
is consistent. In an imperative way, it is very difficult to represent such a relationship elegantly.
Welcome to Reactive Binding
In reactive programming (in ReactiveSwift specifically), the same problem can be solved through binding.
label.reactive.text <~ textView.reactive.continuousTextValues
This statement implies that the text of label
is equal to the text of textView
throughout the lifetime of the label
.
Did you notice something new? <~ is called the binding operator
. The left-hand side of the operator is called the binding target
and the right hand side is called binding source
. We will explore the subsequent articles in the Conquering ReactiveSwift series.
In order to visualize the difference in how imperative and reactive programming works, let’s consider typing out the word “hello.”
In an imperative approach, we model our systems in terms of the mutable state. For example, in the above diagram, we are concerned about maintaining the state of the label
with each additional piece of text entered.
In FRP, we model the behaviour of a system in response to a stream of events. In the above example, we are defining the behaviour of the label
in response to the stream of text. We are not concerned about maintaining a state in response to an isolated event (i.e., each individual keystroke).
There is another benefit to a reactive approach. With reactive code, the behaviour of the label is explicit at the point of declaration. Whereas in an imperative approach, the logic is scattered across various delegate methods. In a long run, it becomes difficult to understand the behaviour of an element, increasing the chance of bugs being introduced.
Some Useful Definitions
Heinrich Apfelmus ([a] Haskell functional programmer), boils down the concepts discussed above, in two statements.
From [a] semantic viewpoint, FRP is all about describing a system in terms of time-varying functions instead of mutable state.
By syntactic criterion, FRP is about specifying the dynamic behaviour of a value completely at the time of declaration.
Next in the series…
Hopefully, this article gives you the motivation to get started with FRP. You can find the sample code here. In the next article, we will discuss the different primitives of ReactiveSwift.
Originally published at fueled.com on August 22, 2017.