Functional Programming Style in JS

In recent years there has been a tectonic shift between traditional programming and Functional Programming style in JavaScript. Primarily, EcmaScript 6 specification is to blame (or to praise, depending on what you think of functional programming style).

The name can be a bit misleading, because the word functional in this case, does not refer to JavaScript functions. Instead, it means functions in a sense of math equations. The name takes origin from lambda calculus.

FP is not for everyone. But if you are a mathematically-inclined coder (you know, you love solving math problems in code) you are going to love Functional Programming.

I can't possibly describe the entire scope of Functional Programming paradigm. You'll probably get the most out of this article if you're coming to the world of FP for the first time ever. It's just a demonstration of basic principles.

What is Functional Programming all about in general?

This actually sounds good!

Yes – FP will require of you a change in how you think about code. But it is often used in real-world production environments, working on a team of software engineers where efficiency and code maintenance matter. In particular, if you are working with the React library, functional programming style is quite common.

Imagine being hired and the lead developer is a huge fan of FP? Instead of having to force-learn the FP style you can get a bit of a head start if you take the time to understand the basics.

Things To Expect From Functional Programming In Practice

Let's take a look at this simple for-loop:

let LIST = [1, 2, 3];

// Part 1: for-loop as an iterator / increment-er
for (let i = 0; i < LIST.length; i++) {

    // Part 2: the statement to execute on each iteration
    LIST[i] = LIST[i] + 1;
}

console.log(LIST); // [2, 3, 4]

We have taken a list, passed it through a two-fold process of 1) iterating over a set of items in the array and 2) incrementing each value by one. Thus taking the original value [1,2,3] and turning it into [2,3,4].

Fair enough. This isn't Google search algorithm.

But it works as example of a traditional iterator using the famous for-loop statement.

Throughout the rest of this tutorial, I will gradually continue changing this for-loop to a more functional style. We'll do this progressively, changing one little thing at a time.

Pure Functions

You can't talk about Functional Programming without mentioning anything about pure functions. But what is a pure function?

The purpose of a pure function is to reduce side effects.

A side-effect in a computer program can occur when you write functions that return unpredictable results or affect data outside of function scope in unpredictable ways – risking the chance of mangling program state.

Once your program state is mangled, it might wreck chaos on the integrity of your program reducing its overall quality. One error leads to another and you become unaware why bugs are even happening anymore. No one wants that.

But a pure function is not a language feature. It is designed by the programmer in such way as to return predictable results given a specific set of arguments.

For example 1 + 2 will always return 3.

On the other hand Math.random() cannot be a pure function. By design it returns a random number each time.

Function Purity is often determined by its return value.

So if your function returns an unpredictable value – even though you're passing the same (unchanging) set of arguments to it – it can be said that you have created, you can say, an impure function.

// Pure - returns same value using same arguments
function sum(a, b) { return a + b; }

// Impure - returns random values regardless what is passed to it
function sum(a, b) { return Math.random() * (a + b); }

Can you stick to writing pure functions? If so you are one step closer to becoming better at functional programming style.

Function purity might not make a lot of sense at first. Especially without a concrete example. But a computer program is not a blatant list of statements. Things you do inside functions may affect overall program state.

Keep in mind though. You can never create an entirely pure program. But if you stick as close as possible to purity it will help you down the road to avoid many common errors that would have happened if you weren't paying attention to these types of rules. It's a habit and a discipline.

It will start making a lot more sense when you see it combined with other Functional Programming style principles.

Let's Rewrite Our For-Loop To Functional Style

Let's utilize the array's map method to rewrite our for-loop.

let LIST = [1, 2, 3];

LIST.map( function(item) { return item + 1; } );

But wait. In EcmaScript 6 which adds features that specifically support Functional Programming paradigm you can use an arrow function. An arrow function further reduces the amount of code written:

LIST.map( (item) => { return item + 1; } );

This can be further turned into the following form by removing return:

LIST.map( (item) => { item + 1; } );

It still works just the same. But looks shorter. More functional. Here functional doesn't mean that we are using JavaScript functions. But that our code is starting to look more like a mathematical equation. Go figure.

Arrow functions still return the value inside {} as long as it is expressed in a single statement. You can even take it further by removing ():

LIST.map( item => { item + 1 });

Remember the for-loop from before? The same exact thing. One statement.

But I should probably say it is almost exactly the same thing.

Arrow functions conceal the value to their scope. This is also a flavor of functional programming. But it means one thing. The original values in the array will not be added to!

We still end up with [1,2,3].

But that's okay -- it is what we should expected from map method:

let LIST = [1,2,3];
LIST.map( item => { item + 1 });
console.log(LIST); // still: [1,2,3] nothing incremented!

Let's move out the function from the map method and store it separately:

let LIST = [1,2,3];
let add = item => item + 1;
LIST.map( add );
console.log(LIST); // still: [1,2,3] nothing incremented!

This looks a bit cleaner. But still our list is not incremented.

This is the paradigm shift. We need to figure out – why not?

Remember how we talked about side effects earlier? The arrow function contains the code within itself without leaking out into global scope. But in Functional Programming this is a good thing. It should expected.

This is purity at work! And yes it does limit us. But it makes code less sloppy.

Solution?

Functional Programming is not simply converting for-loops into smaller and shorter expressions. There is a lot more to it. For example like in the above code the map & arrow function conceal item to its own scope.

Array has a bunch of methods on it that oblige to FP style.

One of them is called reduce. If we can combine map and reduce, we can finally produce the effect of working with array's items in a way where they can be modified without having to be seen by global scope. Concealing the logic of our program to an isolated island. (A good coding practice.)

let LIST = [1,2,3];
let add = item => { return item + 1 };
let sum = (A, I) => { return A + I };
let val = LIST.map(add).reduce(sum, 0);
console.log( val ); // 9

We can also remove return and {} without breaking the code:

let LIST = [1,2,3];
let add = item => item + 1;
let sum = (A, I) => A + I;
let val = LIST.map(add).reduce(sum, 0);
console.log( val ); // 9

Again, this looks a lot more like a math equation (function.) Hence, Functional Programming. Not to be mixed with JavaScript functions! Which appear to have gradually vanished as we kept on applying FP style.

Reducers are functions that "reduce" your result by following a particular rule. As a programmer you choose what it should be. Here, this rule is expressed in the sum function as A + I. That is, Accumulator + Item. Essentially, this is what our for-loop was doing earlier.

An accumulator is inherent to a reduce operation. It's exactly what it sounds like. The accumulator keeps track of the compound effect of the operation.

The second parameter of reduce is set to 0. This sets the accumulator to 0.

This way we are starting with 0 in the counter. Once this code is complete this accumulator will become the return value. (Stored in variable val.)

As the code runs, we keep adding the value using this new sum function.

The result is 9.

Because we first added 1 to [1,2,3] and produced [2,3,4].

Then we ran reducer on it to add up all values in [2,3,4] together and return.

And so finally 2 + 3 + 4 = 9.

So you can see here how it's just a slightly different mentality than a for-loop.

Code looks less ugly this way. And it works almost like a math formula.

The Video Tutorial

My video tutorial about Functional Programming Style in JavaScript:

Functional Programming Style in JavaScript

Note: much like this article – this is just an intro created for someone diving into the subject of FP for the first time and not an entire course or a comprehensive study of Function Programming.

Many of my tutorials are written for first time beginners. Like this one. I wrote this tutorial as an introduction to Functional Programming style. Not as an explanation of the entire FP paradigm–which is so much more.

Not everyone will like FP. But if you do, it is probably a good idea and look beyond map and reduce methods. Good luck out there!

Don't Panic. It's only JavaScript News.

When I release something, I make sure it's worth reading or taking a look at — at least once.