One trend that has started gaining some serious traction in the past couple of years is functional programming. Unlike an object-oriented approach, which encourages decomposition of a program into ‘objects’ which relate to a particular domain, a functional approach guides the developer to decompose a program into small functions, which are then combined to form an application. Once confined to the halls of academia, it has recently seen a resurgence as a popular tool to solve a number of the problems that we face in modern development, especially complex applications and distributed systems.
Trailing along behind the functional cheerleaders are a whole host of super-powered functional languages. These include such venerated languages as Haskell, Lisp and Erlang, as well as more modern interpretations including F# (a .NET language), Scala and Clojure (on the JVM), Rust (a server-side language) and Elm (a language based on Haskell for building web front-ends).
Before we dive in to building our front-end, I want to touch on a couple of important functional concepts that we can use to make our app more robust.
We all know about functions - they are the building blocks of any program. What makes functional programming so special? Pure functions are part of the answer. A pure function is a function where the return value is determined only by its input values, and which does not alter any external state. This has two important implications:
- For a given input the function will always return the same result, no matter how many times it is called. This means that our application is completely predictable - if we know what inputs it will receive, we can be confident of the outputs.
- Calling the function will not result in any observable side-effects. We can be certain that we will not experience any undesirable ‘emergent behaviour’ arising from the interactions between different functions.
Building an application from pure functions enables us to more easily reason about the behaviour of an application.
An immutable object’s state cannot be changed once it is created. If we want to change the object, we can’t simply set a property on the object - we have to return a whole new object with that one property changed. This might seem arduous, but it comes with big advantages.
One of the advantages of immutability is in asynchronous programming: if a thread is operating on an immutable object, it can be sure that it is dealing with the latest version of the object. This allows multiple threads to operate simultaneously without worrying about what the other threads are up to.
=== is always more readable than a deep-equals!).
Another advantage to immutability is that it encourages us to keep our functions pure - if we can’t modify an object from inside a function, we can’t modify state external to the function. This means that we can be sure of making the most of the very tangible benefits of pure functions.
Currying and Point-Free Programming
A curried function is one which returns a function for every argument until the last argument is supplied. As an example consider the following code, which adds two numbers:
We can call
add with each argument provided simultaneously (invoking the function after each argument). Alternatively, we can store a partial application of the function - here, we are storing
add3. This partial application can later be applied to further arguments.
This is a good approach if we are going to re-use the function multiple times, or if we want to be more explicit about the meaning of a function. A good example is the following, which assigns “modulo 2” to “is odd”, resulting in more readable code:
This style of assigning partially applied functions is known as point-free programming. A good explanation of point-free programming can be found on the Haskell wiki. As the article notes, care should be taken when using point-free programming with higher-order functions (functions composed of functions) as it can easily result in code that is more obfuscated and less easy to reason about - precisely the opposite of what we want!
React is a great tool for building the view layer in an MVC-style web application. Rather than providing a full single page application framework like Angular, it focuses simply on rendering data, and it is very good at doing this. This is not an introduction to React, so I won’t go into too much depth here (the React Docs are an excellent place to start learning about React). Instead, I want to focus on what makes React an excellent choice for our functional front-end.
React applications are separated into components. These components should encapsulate a particular piece of functionality, and can be combined into more complex components and eventually into a whole application. The job of most components is to simply render data that it is given (for example, to display a single comment in a forum), or manage some small interaction (the click of a button, entry of text into a form). This sounds a lot like functional programming!
In fact, React makes it really easy to build components out of functions. Here’s the canonical “Hello, world!” example as a React component:
Here our component -
HelloWorld - is defined as a pure function. React can then render it just as it would any other component - we do this by calling
ReactDOM.render with our component and a DOM element (which we have given the id
That html-looking syntax there is actually JSX.
<div></div> returns a React element that indicates that an html
div element should be rendered here. We might also want to render another React component - we can reference our HelloWorld component using
What if we wanted to re-use a component for displaying different data? In the following example, our component greets someone by name:
We’ve defined a component that can say hello to anyone by name. Our component accepts some properties (
props) that have been set by its parent component - you can see this inside the
ReactDOM.render method - we are passing the prop
name="Bob" to the
In general, this is how components are built in React - a parent component will define some props that are passed down to its children. When
ReactDOM.render is called React builds a virtual representation of the DOM and renders to the real DOM. It looks like every time we call
ReactDOM.render the entire real DOM is re-rendered, but this is not the case: behind the scenes React builds a new virtual representation of the DOM and does some very clever comparisons to work out what changes to make to the real DOM. Again, the docs have an excellent explanation of how this comparison - normally O(n3) - can be turned into an O(n) problem with a couple of assumptions. This makes React’s approach of re-rendering the whole virtual DOM practical.
This is all great stuff, as it allows us to build really simple components that are easy to reason about.
So we’ve built a component using just functions - let’s see what happens if we stick a few together!
Functions as Components
I’ll be building a simple forum app which displays comments. As far as possible I’ll try to keep it functional - that is, use pure functions with immutable data. We’ll start by breaking down our app into pure functional components that will display our comments, and then we’ll plug in some data.
Let’s start with the top-level component -
App. Just as before, we can define our component as a pure function. Our inputs will be the title and subject of our forum discussion, and our list of comments. On top of that, we’ll also display our title, subject and list of posts using
PostList components like good React programmers.
Pretty straightforward, right? It’s really easy to see what’s going on here. Our
App component is rendering
Post components inside a
div element. It’s passing down the
title to the
Title component, the
subject to the
Subject component and the
posts to the
So far, so easy. Let’s take a look at
PostList - it’s calling
postComponents to generate the
Post components from the array of posts. What does this
postComponents look like? We can use currying here:
This uses Ramda’s
map function to partially define a function that maps the given expression (a conversion from post to
Post component) over an array of posts.
For those unfamiliar with the functional style, this can be quite difficult to follow so I’ll break down what it’s doing. We want our
postComponents function to convert an array of posts into an array of components. A first pass at a function that does this might start with an empty list and add components to it one at a time:
This is fine, but it is quite verbose and not very readable. We need to follow the flow of the function through variable initialisation and loop to determine that it will result in an array of
Array.prototype.map is up to the job:
This is better, however it is still verbose. We need to define a whole function in order to define our customisation of the
map function. This is where currying can help us - it allows us to store references to partially defined functions that we can use later.
We could just use the
posts.map function directly inside our
PostList component, however storing a reference to the function promotes code re-use and allows us to keep our code very readable.
Now that we have our list of
Post components, let’s take a look at the
Post component itself. We need to display an author and a comment - so let’s break those up into components too.
Take a look at that - they’re all pure functions! The
Post component has an
author and a
comment in its
props, which it passes down to the
Comment components respectively.
Author component is doing something similar to the
PostList component - it’s calling the
authorComponents function. This function should return an array of components to display all properties that are present on the
author object. This is defined as follows:
The ES6 arrow function syntax replaces the
function declaration. This makes it semantically clearer that “
author maps to the following array” or “
author maps to the following element”.
Our use of the ternary operator (?:) makes it easy to shorten
if-else blocks in order to make our code more readable.
Finally we recognise that when a property is present on an object, the first argument to the ternary expression will evaluate to true; if it is missing, it will evaluate to false. This makes it easy to conditionally include or exclude React elements based on properties in our object.
Let’s recap - we now can now display a forum and thread of posts, with each post displaying some information about the author and the comment. And we’ve done all of this using nothing but functions. Not only that, but we haven’t modified any state outside of our functions. This has profound implications for testing - it means that we can write tests for our functions and be sure that no external interference will change their behaviour - that’s pretty impressive.
Generating the Sample Data
For this example I’m going to simulate a few comments from a few authors.
Here, we have a couple of interesting functions to generate sample data.
nthWrapped uses Ramda’s
pipe function to build a function that takes the modulo of the input with the length of the array (using the handy
flip function to swap the order of the first two arguments of
mathMod) and then returns the element at the resulting index.
nthPost takes an index and merges the result of calling
nthWrapped on both the
comments arrays into a single result. We can use this as an argument to Ramda’s
map function to generate another function that returns posts in a given range.
We have effectively provided a “stub” version of the
postsInRange function - we could easily swap this out for a real version. This is one of the great advantages of functional programming - because each of the functions are small and simple, and because they do not modify anything external to the function itself, they are easy to replace.
Rendering the App
Once we have our data, we can simply call
ReactDOM.render, as we saw in the examples. We can use Ramda’s
range function. I’ll then render them into the html element with
id="app". Here’s what that looks like:
Bonus - RxJS Stream
Great - we’ve got an app that renders comments! But we can do better than that - we might be looking at a really popular post, and we want to view comments as they come in. Wouldn’t it be nice if we could render a stream of incoming comments? Thanks to the functional style in which we have written our app, we can!
Instead of rendering posts in a given range as in the previous example, we want to call
render every time a new post is available from our stream. We can let React do the heavy lifting to ensure that a minimal set of updates is applied to the DOM.
Here’s the code:
We set up a source for our posts. This is simulating a post coming in every two seconds, using the same
nthPost function that we defined in our previous example. This could be swapped out for real data in a production app.
We then set up a subscription to our event source. This is doing a couple of interesting things.
scan is a method on the
postSource. It acts very much like the
reduce function - we provide an initial value and an accumulator, and it returns the result of calling the accumulator over all of the elements in the stream. The difference between
scan in RxJS is that
scan will return intermediate values - it will return every time the stream emits an item - whereas
reduce will wait until the stream has completed. Our accumulator here is simply appending the next value to our current accumulated value.
The result after
scan is called is an observable that emits an array containing all the posts emitted so far, every time a new post is added.
map is then called to return a React element that wraps our posts - here defined as the
app function. This also returns an observable, which we can subscribe to in order to render our posts.
This amazingly small amount of code achieves something quite complex - we now have a dynamic application!
Is Functional Programming The Way Forward?
I think that we can learn a lot from the functional paradigm and that it can result in cleaner, more readable and more robust code that is also easier to maintain. Though this post is only meant as an introduction, hopefully it will inspire you to look into functional programming and perhaps use some of the approaches outlined here.
Where to go next? If you’re using React, then redux provides a functional approach to managing state for your apps. It has a large and growing ecosystem of tools and middleware and comes with features such as time-travel and undo-redo practically for free - thanks to its use of immutable states. Colin’s written a post on that too!.
There are frameworks out there that take a much stricter approach to building front-ends in a functional style - elm takes its cues from Haskell and provides a pure functional experience for programming in the browser, while Reagent and re-frame allow you to build front-ends with ClojureScript.
You can check out a version of this app on jsbin.