The Wonderful World of Functional Programming

A Brief Overview

Functional programming is getting a lot of love these days. When most developers discuss functional programming, they tend to refer to it as a binary condition — functional or object-oriented. However, functional programming is more of a paradigm — existing on a spectrum approaching purely functional. Can you build a non-trivial, purely functional system? Allow me to conveniently avoid answering that question by saying you don’t have to. Like most things, too much of anything is bad for you. A healthy mix of both functional and traditional object-oriented constructs is likely the sweet spot for most non-trivial systems.

What is Functional Programming (FP)?

Functional programming (FP) is a bunch of things. FP uses pure functions as the fundamental building block for building software. A pure function is one which:

  1. Causes no side effects (observable interaction which is not a return value)
  2. For any set of inputs, will always produce the same output

Consider the following JavaScript code:

Mutate array — no good!

We’ve successfully mutated our array arr , but we’ve reached outside of our function scope and mutated data outside of it. This is an example of a side effect and can lead to problems later down the road if we want to use the original version of that data. Also, the function itself has no explicit inputs, and so if arris modified, the same invocation of mutateArr will produce a different output, which violates our first functional constraint. Furthermore, we print the result of the computation from within the function. Logging (or any other form of I/O) is another example of a side effect. A slightly better implementation would be:

Mutate array — slightly better

So, now we’ve created a pure function which does not cause any side effects. Our original data is untainted and we’ve moved our log statement outside of our function. We’re purely functional now, right? Nope! Take another look at the mutateArr function. Do you see all that looping code for (let...) ? That’s a problem! This brings us to the next characteristic of functional programming — declarative constructs.

Operation: Iteration Obliteration — Favor Declarative Over Imperative

Given a collection of items, you want to execute some task for every item in the collection, or perhaps mutate every item in an array like in the above example. A for-loop gets the job done, but you have to specify the details of how the task gets completed — this is known as imperative programming. For instance, we created a variable, k which tracks our current index. We initialized k , specified when to stop the iteration with regard to the value of k and we increment k at the end of each iteration. None of that code has anything to do with the task at hand. Also, we explicitly create a new (empty) array into which or mutated data gets manually placed. We need a declarative way of performing this task. Declarative programming means you establish what should happen and not concern yourself with the details. Let’s try this again using JavaScript’s map() function.

Mutate array — pretty good

We went from six lines of code to one line for the body of our mutateArr function. If you really want to condense the mutateArr code, you can employ JavaScript’s arrow functions more aggressively:

Mutate array — baller!

Immutable Data Structures

Immutability is another core part of functional programming. If you recall in our previous example, we printed our original data arr as well as our mutated result. It was important that we not modify the original data. JavaScript’s higher order functions (map, reduce, etc.) always return a new array as opposed to modifying the new original data.

Constructing your application using immutable data structures gives you many benefits including (but not limited to) complete state history. Having the ability to “rewind” state is extremely useful when debugging code. As you might imagine, retaining complete copies of old data can quickly add to your memory consumption. There are however memory management techniques which address this problem. I won’t delve into details today but it involves trie structures and pointers. You can read more about immutability and persistent data structures here.

Wrap Up

Any of the above concepts can easily be its own lengthy blog post. The idea here is to illustrate the functional paradigm and present a different way of writing code. Remember, the best approach is always the approach which makes sense given the context of your problem set. Consider FP another tool at your disposal and choose wisely!

DISCLOSURE STATEMENT: These opinions are those of the author. Unless noted otherwise in this post, Capital One is not affiliated with, nor is it endorsed by, any of the companies mentioned. All trademarks and other intellectual property used or displayed are the ownership of their respective owners. This article is © 2017 Capital One.

For more on APIs, open source, community events, and developer culture at Capital One, visit DevExchange, our one-stop developer portal.