Functional JS #2: Functions. Duh!

Krzysztof Czernek
DailyJS
Published in
5 min readOct 16, 2018

This is a second part of the “Functional JS” series. Go to the beginning of the series here.

“close-up photo of factory” by Taton Moïse on Unsplash

Introduction

Now that we know why learning functional programming practices can help you become a better programmer, let’s jump into the fun stuff.

In this part, we will focus on the vocabulary and basic concepts connected with functional programming.

Sadly, there won’t be a lot of code involved. On the bright side, once we understand the terminology, we will be able to discuss more complex subjects comfortably.

Functions

As you can imagine, the most important thing in functional programming is, well, a function.

We all know a function when we see one. It’s basically an organised (and named, for the most part) piece of code that does stuff.

When it comes to FP, though, we are interested in a specific point of view on what a function is: a mathematical one.

Math… not even once?

Even though we won’t have to deal with algebra ourselves, we need to acknowledge that functional programming is deeply rooted in maths.

And in simple, mathematical terms, a function is a machine that produces an output given an input.

The one interesting thing is that there can only be one output for a given input. Which means, if we provide the function with the same input, we expect it to always do the same exact thing, and return the same value.

This sounds trivial, but it’s actually a strong requirement. This mathematical definition has significant consequences:

  • A function can not depend on anything except its input (arguments)
  • A function has to return a single value
  • A function needs to be deterministic (can’t use random values, etc.)

Functions that meet those criteria are called pure functions in programming, and they are crucial to the functional paradigm.

Pure functions

Let’s look at some examples of functions in JavaScript to build up an intuition about what a pure function is.

The coin function is not pure, because it doesn't always produce the same result given the same (empty) input - it's not deterministic.

The uppercaseName function is not pure, because it depends on a variable that's out of its control. We can't be sure it will always produce the same result given the same arguments.

The happyBirthday function is not pure, because in addition to accessing out-of-control variables, it does not return anything.

The calculatePrice function is pure. It doesn't use any variables out of its control, is deterministic, and we can confidently say that it will always return the same result for the same combination of input arguments.

So what?

Why does it all matter? There are a couple of reasons why pure functions are better than impure ones:

  1. They are easier to read
    In order to understand what a function does, you only need to read its body.
  2. They are easier to reason about
    There’s no need to look for external dependencies, the context in which the function is called, etc. None of this matters for pure functions.
  3. They are easier to test
    If you want to test a function that is pure, you only need to call it with some arguments and see if the result is what you wanted it to be. No complicated setup required.
  4. They can be more performant
    If we know that for a given input, the function will always produce the same output, we can cache (memoize) the result so we don’t have to recalculate it when the function is called again.

Using pure functions makes your code more maintainable — because it makes it easier to manage side effects. In the next parts we will learn what side effects are and why, sadly, computer programs can’t be pure functions “all the way down”.

Now that we know what pure functions are, let’s focus on the next function-related term: first-class functions.

First-class functions

A “first-class function” is, unlike the “pure function”, not a practical concept that’s useful on a daily basis. It does, however, come up when thinking about characteristics of programming languages.

You can say a programming language has “first-class functions”, if functions can be used just like any other values, i.e.:

  1. they can be passed around,
  2. they can be assigned to variables,
  3. they can be stored in more complex data structures, like arrays or objects.

Functional programming without first-class functions would be impossible (or at least very awkward). Here’s an example illustrating why functions are first-class objects in JavaScript:

As we said, in JavaScript functions can be passed around — between different functions. But… why would you want to do that?

Well, passing functions in and out of functions is a common practice in functional programming — and a very powerful one. Which brings us to…

Higher-order functions

Functions that “operate” on other functions are called higher-order functions. By operate, we mean they can either (or both):

  • take other functions as arguments,
  • return other functions.

The examples of this are really common in the JavaScript world. One of the examples is the Array.prototype.map function in the standard library. It takes a function and applies it to every element in the array:

When it comes to returning functions from other functions, here’s an (a bit contrived, I have to admit) example:

As you can see, these functions (map and makeGreeter) don't accept/return regular values as we know them. They operate on functions.

You may already be familiar with some of the higher-order functions, like:

  • map,
  • reduce,
  • filter,
  • compose,
  • forEach,
  • … and others.

Functional programming is all about composing small, reusable, and generic functions into more complex ones. Given that, you can expect us to be discussing a lot of different higher-order functions in the posts to follow.

For now, this is all of the basic function-related terms we will need to start our journey.

Next time, we will focus on state in functional programming — how to manage it, how to avoid problems with it, etc. We’ve already brushed the surface of this (when discussing pure functions), but there’s much more to it!

We’ve already learned a lot, and I hope you’re as excited for the next part as I am!

--

--