FP in vanilla JavaScript: a rookie’s intro

Riccardo Odone
5 min readDec 10, 2017

--

If I were asked to perform a slam dunk I’d have to go through months if not years of trainings, blood and tears. Or I could just go to the Moon and easily do it right away since I’d weight six times less there.

The idea is that I can greatly simplify my work by moving to a space where the rules are more favourable for the problem at hand.

It just so happens that writing code is like building universes and going to the Moon is a viable thing to do.

The procedural universe

Let’s take a look at some code

The idea is that there’s a string containing an array of strings; procedural parses it as JSON, then takes the first element of the array and formats it.

Problem is that in this universe we have to deal explicitly with all sorts of possible failures. In fact:

  • JSON.parse(string) could fail in case string contained invalid JSON;
  • array[0] would return undefined in case the array was of length 0.

I already hear some haters back there saying I’m using a straw man by showing badly factored procedural code. So let’s refactor a bit

Or

Problem is that we are obliged to deal with trys and ifs and cannot really hide them easily anywhere.

Well, let’s move to another universe and see what happens there.

The functional universe

Waaaaaaaaat the devil is going on there?

Let’s forget about parse, first, upper andshout for now. We are going to take care of lower level details later on.

The first thing to notice is that I don’t really know how to write functional code, so you got the rookie’s version of it. At the same time, I wanted to limit the amount of new concepts needed.

What the hell are map and chain doing? And what about Right and Left?

Let me tell you a secret: it’s not important to understand them. We just need to understand the intuition behind.

Dipping the toes in FP

First of all, let’s just forget what map means

Ok, now we can talk.

Imagine for a moment that you stopped using primitives. Instead, you put all of your primitives inside of a box.

Now, map is a function that allows you to interact with the boxed values. In other words, it allows running functions against values contained in a box and then return the boxed value.

On the other hand,chain is a function that allows running functions against values contained in a box and return them unboxed.

Box alone is as useful as a waterproof towel. But it enables us to understand other types of boxes like Right and Left.

They are both subtypes of Either and are used whenever an operation could succeed and return something (e.g. Right('success')) or fail (e.g. Left('some error')).

Being subtypes of Either enables polymorphism because they both implement map and chain. In fact, with a Right, map and chain work as described above (i.e. Right behaves like a Box). With Left, map and chain just pass the box forward and perform no work.

As I said, it’s not important to understand how they work internally. The most important part is the intuition: whenever an operation succeeds it returns a Right, therefore subsequent maps and chains will go on working with the contained value. Otherwise, a Left would be returned and all subsequent operations wouldn’t be run.

This is extremely powerful because as long as a failure (e.g. null, error) is contained in a Left the caller can be totally ignorant about it and the values contained won’t ever be used and create problems.

In the end, there’s not much to think about besides wrapping in Right or Left return values and mapping whenever there’s a box and chaining whenever there’s a nested box.

Well, all of this is fun like building a boat in a bottle. But why the hell should I care?

Because of simplicity and composability. Functional programming is all about it: small, declarative and pure functions that are easy to read, test and compose.

Back to the functional universe

There are no trys orifs in the functional code.

That’s because they are treated as implementation details. It’s the Either through Left or Right taking care of it for us.

Now we can dissect the other functions. First the ones directly used.

As you can see first and parse are the only functions doing some interesting stuff. But still no signs of ifs and trys.

It’s only when we get to the library level functions that we see the ugly stuff. Luckily it’s hidden in the basement and we can totally forget about it.

As you can see,fromNullable and tryCatch just take care of boxing the outcome of their work into a Either.

Altogether the functional code is as follows

Isn’t this a beauty? I haven’t been this excited since my Lego childhood.

Adding functionality

Now, what if we decided that we are passing an array of JSON strings and not just one string? And wait, let’s say the array contained integers and not strings.

This is all it takes. Still declarative, still well factored and we didn’t have to go and touch code any level deeper than that. None.

Outro

This is just the tip of the iceberg. There’s many other things like map and chain or Box and Either. That means we can slam dunk even harder!

Hungry for more? See how I refactor the functional code in the follow up post.

Pointers

Almost all of what I’ve covered here was stolen from a brighter mind than mine. So just do yourself a favour and

Thanks Brian Lonsdorf for showing me that FP is much more than using map and reduce on vanilla JS arrays. And that you can have fun bringing math into programming.

Get the latest content via email from me personally. Reply with your thoughts. Let’s learn from each other. Subscribe to my PinkLetter!

--

--

Riccardo Odone

🏳️‍🌈 Pronoun.is/he 💣 Maverick & Leader @Lunar_Logic ✉️ PinkLetter Odone.io/#newsletter 🎓 Student & Teacher of Timeless Software Skills