**A Gentle Introduction to Functional Programming**

Functional Programming (often abbreviated as FP) is a programming paradigm that heavily utilizes functions to change how application state is managed. It is declarative rather than imperative, meaning programming in a functional manner tells your code what to do, rather than telling your code how to do it.

Functional programming has a very steep learning curve, mainly because it’s very different than how most applications are written. However, once the basic patterns are learned, programming with the FP paradigm tends to result in more stable applications, because of its predictability.

This article will break FP into three concrete steps. Of course, there’s a lot more than just three steps, but this will give you a great start in learning how FP works.

1. Pure functions

2. Functional Composition

3. Currying

**Pure Functions**

Pure functions are simply functions that take an input and generate an output. They do not perform any side effects. Given the same input to a pure function, you can expect the same output. Run the same input through the same pure function and you should always get the same answer, each and every time.

Here’s an example of a pure function:

`const add = x => x + 2`

add(2) // always get 4

add(2) // still 4

add(2) // still 4

When you call `add(2)`

, you get 4, no matter how many times you call it.

Example CodePen:

However, here’s an example of an impure function:

`let y = 2`

`const add = x => x + y`

`add(2) // get 2 at first…`

`y = 5`

`add(2) // now, you get 7!`

Example CodePen:

Since the add function depends on y, which is outside of the scope of the function, it is considered impure. Its output can change because the function does not only depend on its own arguments.

Another factor of pure functions is that it does not cause any side effects. That is, anything outside of the scope of the function stays the same.

Here’s an impure function that breaks that rule:

`let y = 2`

`const add = () => y += 2`

`add() // 4`

`add() // 6`

Example CodePen:

When writing pure functions for the purposes of functional programming, you want to be sure that any output is derived deterministically from the functions arguments and/or immutable constants. For example, you could have a constant called PI, to store the transcendental number, and your function can depend on it because that number is not going to change.

Usage of pure functions is essential to understanding functional programming. If the state is changed outside of a function, a lot of bugs can be introduced due to impurity.

Now, if you’re a web developer, it’s almost impossible to write everything in pure functions. For example, a simple console log is considered a side effect. Any function with a side effect is by definition not pure. A console log is a pretty harmless side effect, but what about DOM manipulations? What if I want the results of my mapping function to be written to the DOM? Do I need to pass the entire DOM in as a function, and then return the new DOM out?

Well, that’s one of the purposes behind libraries such as React and Vue. They wrap up all of the DOM manipulating side effects into the library so that DOM can be written to deterministically (as a function or props or state), and you can still use pure functions to produce React or Vue components.

**Functional Composition**

One of the main allures of functional programming is the fact that it allows you to compose functions. This is a fancy way of saying, put the result of a function in another function. It could look like this:

`const add10 = x => x + 10`

`const double = x => x * 2`

`add10(double(5)) // 20`

`double(add10(5)) // 30`

Example CodePen:

We can use a function called compose to express functional composition. Here’s a simple compose function:

`const compose = (...`

`fns`

`) => arg => `

`fns`

`.reduce((acc, fn) => fn(acc), arg)`

In case you aren’t familiar with the spread operator, we are allowing compose to take a variable number of arguments, and we store that in an array we are naming fns, the compose function that takes in a bunch of functions and then returns a new function that takes in the argument. Then the reduce function sequentially calls each function from left to right, passing in arg first, then passing that result into the next function.

By using this compose function, we can now create new functions with it:

`const add10ThenDouble = compose(add10, double)`

`const doubleThenAdd10 = compose(double, add10)`

`add10ThenDouble(5) // 30`

`doubleThenAdd10(5) // 20`

Example CodePen:

Now, be very careful. The order of things can get very confusing. Note the equivalence of the functions:

`add10(double(5)) === doubleThenAdd10(5) // true`

`double(add10(5)) === add10ThenDouble(5) // true`

It may seem backwards, but your code actually goes from innermost to outermost parentheses (remember PEMDAS or BODMAS from elementary school). So for add10(double(5)), it doubles 5 first, then adds 10. When doing functional composition, we compose them in the order of computation, not in the order of writing when we write our code. However, it should be simple enough to write a function that applies the compose functions in reverse, so that it appears in the same order as writing the code.

**Currying**

Sometimes we want to compose functions that take more than one argument. How could that be possible? For example, if I had a few basic mathematical functions:

`const add = (x, y) => x + y`

`const subtract = (x, y) => x - y`

`const multiply = (x, y) => x * y`

`const divide = (x, y) => x / y`

I’d like to be able to compose a bunch of these arithmetic functions together, but how?

This is where a concept called currying comes in handy. Currying converts a function that takes in a certain number of arguments (which is called its arity), and if supplied fewer arguments than it takes, return a new function that takes in the rest of the arguments. This may sound bizarre, so here is how we would curry the arithmetic functions above:

`const add = x => y => x + y`

`const subtract = x => y => y - x`

`const multiply = x => y => x * y`

`const divide = x => y => y / x`

Now, we can use functional composition to perform any amount of arithmetic chaining:

`compose(add(5), subtract(1), multiply(4), divide(2))(1) // 10`

Example CodePen:

However, what if we had more complex functions that took in more than just two arguments?

`const sum = (x, y, z) => x + y + z`

`const curriedSum0? = x => y => z => x + y + z`

`// or is it`

`const curriedSum1? = (x, y) => z => x + y + z`

`// or perhaps`

`const curriedSum2? = x => (y, z) => x + y + z`

The answer is it could be all of the above. You should be able to call a curried function with arguments in the same list, or applied separately, like so:

`curriedAdd(3)(4) // 7`

`curriedAdd(3, 4) // 7`

`curriedSum(1, 2, 3) // 6`

`curriedSum(1)(2)(3) // 6`

`curriedSum(1, 2)(3) // 6`

`curriedSum(1)(2, 3) // 6`

Thankfully, just like there’s the compose function we made above, there’s also a curry function. Here’s a simple implementation:

`const curry = (uncurriedFn, ...args) => {`

` // you can get the arity of a function by calling length on the `

`fn`

` const`

` arity = uncurriedFn.length`

`const accumulator = (...accArgs) => {`

` let argsCopy = [...args] //`

` if (accArgs.length > 0) {`

` argsCopy = [...argsCopy, ...accArgs]`

` }`

` if (args.length >= arity) return uncurriedFn.apply(null, argsCopy)`

` return curry.apply(null, [uncurriedFn, ...argsCopy]) // recurse`

` }`

` // if any args passed in, pass them to the accumulator`

` return args.length >= arity ? accumulator() : accumulator`

`}`

Of course, this only works if there are zero optional arguments. Every required argument of the function you wish to curry must be named for fn.length to work. If there are any optional arguments, then currying will not work. This is why some functional libraries like lodash or Ramda split the variadic functions into multiples; for example, lodash’s regular get function, which accepts two arguments, three with a default, is split into get and getOr in the functional variety of the library.

Now, we can do functional composition to use our new sum function:

`const [`

` curriedAdd,`

` curriedSubtract,`

` curriedMultiply,`

` curriedDivide,`

` curriedSum`

`] = [`

` add,`

` subtract,`

` multiply,`

` divide,`

` sum`

`].map(i => curry(i)) // this simply creates curried versions of our functions`

`compose(add(5), subtract(1), multiply(4), divide(2), sum(3, 4))(1) // 17`

CodePen Example:

Not only is this more concise, but there are no extra variables, and the original variable nums is left untouched.

**The Filter Function**

The filter function is another native pattern of JavaScript. It operates on an array and returns all values that adhere to the filter function.

Here’s a naive approach using beginner JavaScript methods:

`const nums = [1, 2, 3, 4, 5]`

`let evenNums = []`

`for (let i = 0; i < nums.length; i++) {`

if (nums[i] % 2 === 0) {

evenNums.push(nums[i])

}

`}`

`// some students may also use forEach:`

`nums.forEach(num => num % 2 && evenNums.push(num * 2))`

`And here’s how you could use filter for the same thing:`

`const evenNums = nums.filter(num => num % 2 === 0)`

Example CodePen:

So it runs each num of the nums array through the filter function, and if the filter function returns truthy, the num gets to stay in the filtered evenNums array.

**The Reduce Function**

The reduce function may be familiar to anyone who has used Redux before (after all, it runs on reducers).

The reduce function operates on an array, and it contains an accumulator. This could be a sum, it could be an array, it could be the intermediary results of functional composition. The point of reduce is that it’s extremely versatile. In fact, I will leave it as an exercise for you to recreate map and filter using the reduce function.

The simplest way to show how the reduce function works is by using a sum.

First, the beginner way:

`const nums = [1, 2, 3, 4, 5]`

`let sum = 0`

`for (let i = 0; i < nums.length; i++) {`

sum += nums[i]

`}`

`// some students may also use forEach:`

`nums.forEach(num => sum += num)`

As mentioned before, this leads to an impure function. We define a sum and it changes over time. We don’t want that.

With reduce, we can specify our starting value, and then we can specify what we want to do at each step of the iteration:

`nums.reduce((accumulator, num) => accumulator + num, 0)`

`// alternatively`

`nums.reduce((accumulator = 0, num) => accumulator + num)`

This starts the accumulator at zero, and at each step, we pass the return value of the accumulation function as the accumulator for the next iteration.

Here’s how it works piece by piece:

`const sum = nums.reduce((accumulator = 0, num, i) => {`

console.log(‘Iteration’, i, ‘, accumulator’, accumulator, ‘, number, num) // for clarity

` return accumulator + num`

`})`

console.log(‘Final sum:’, sum)

We will see the following logs:

Iteration 0, accumulator 0, number 1

Iteration 1, accumulator 1, number 2

Iteration 2, accumulator 3, number 3

Iteration 3, accumulator 6, number 4

Iteration 4, accumulator 10, number 5

Final sum: 10

Let’s see how we can use reducers to make a simple state management system:

`const initialState = { counter: 0 }`

`const counterReducer = (state = initialState, action = {}) => {`

` switch (action.type) {`

` case ‘INCREMENT’: {`

const { counter } = state

` return { ...state, counter: counter + 1 }`

}

case ‘DECREMENT’: {

const { counter } = state

` return { ...state, counter: counter - 1 }`

}

` default:`

` return state`

` }`

`}`

`const state0 = counterReducer()`

`// { counter : 0 }`

`const state1 = counterReducer(state0)`

`// { counter: 0 }`

`const state2 = counterReducer(state1, { type: ‘INCREMENT’ })`

`// { counter: 1 }`

`const fakeState = counterReducer(state1, { type: ‘INCREMENT’ })`

`// still { counter : 1 }`

`const state3 = counterReducer(state2, { type: ‘INCREMENT })`

`// { counter: 2 }`

`const state4 = counterReducer(state3, { type: ‘DECREMENT’ })`

`// { counter: 1 }`

`const anotherFakeState = counterReducer(state3, { type: ‘DECREMENT’ })`

`// still { counter: 1 }`

`const state1Branch = counterReducer(state1, { type: ‘DECREMENT’ })`

`// { counter: -1 }`

initialState // untouched: { counter: 0 }

As you can see, by keeping the reducer a function of a state and an action, we can maintain a history of all of our states, and we can even “time-travel” and see what would happen if we used a different action at a specific point in time. This makes Redux really simple to test, because once you know the inputs, the outputs should be predictable.

By the way, the Redux example above is a perfect example of where I would use currying and functional composition. Let’s say I wanted to keep track of the counter and how many times the user clicked a button, any button. I’m going to use a function called set which is a curried function that takes in the key, the intended value, and the object to update. It does so in an immutable manner, without mutating the original object. The set function can come from the lodash FP library, but I’ve implemented it myself to reduce the amount of “magic” going on.

`const initialState = { counter: 0, `

`timesClicked`

`: 0 }`

const set = curry((key, value, obj) => ({ ...obj, [key]: value }))

`const counterReducer = (state = initialState, action = {}) => {`

` switch (action.type) {`

` case ‘INCREMENT’: {`

const { counter, timesClicked } = state

return compose(

set(‘counter’, counter + 1),

set(‘timesClicked’, timesClicked + 1),

)(state)

}

case ‘DECREMENT’: {

const { counter, timesClicked } = state

` return compose(`

set(‘counter’, counter - 1),

set(‘timesClicked’, timesClicked + 1),

)(state)

}

` default:`

` return state`

` }`

`}`

CodePen Example:

As you can see, whenever the action.type matches, we pipe the state through the functions passed into the compose function. It’s like calling set(‘counter’, counter + 1, state) then set(‘timesClicked’, timesClicked + 1) on that new state.

**Some Real-World Examples**

I use functional composition all the time in my Node.JS and ReactJS apps. For example, to parse a URL like /users/me?apiKey=foo, you could use a function like this:

`const { flow, split, head, tail, filter } = require(‘lodash/fp’)`

const getUserPath = flow(

split(‘?’), // splits string by ?, creates an array

head, // gets the first value

split('/'), // splits string by /, creates an array

tail, // gets all but first element of array

filter(v => v) // removes all empty strings and falsey values

)

getUserPath('/users/me?apiKey=foo') // [‘users’, ‘me’]

Example CodePen:

This will return an array that reads something like [‘users’, ‘me’], which I can use to query resources or do whatever I want. Flow works like compose; I prefer it to compose because lodash’s native compose function goes from right to left, which is weird for me.

Note that we could write a function called isTruthy and make it something like v => v, then we could use filter(isTruthy) to make our code read a bit better. However, though not entirely necessary, that’s one of the options that are available to you in FP.

I’ve also used this to work with large datasets, using the Highcharts library.

`const { map, sum, filter } = require(‘lodash/fp’)`

const getAvgInView = series => {

const data = flow(

filter(point => point.isInside),

map(point => point.y)

)(series.points)

return (sum(data) / data.length).toFixed(1)

}

const s = {

` points: [`

` { x: 0, y: 10, isInside: false },`

` { x: 1, y: 100, isInside: false },`

` { x: 2, y: 50, isInside: true },`

` { x: 3, y: 10, isInside: true },`

` { x: 4, y: 30, isInside: true },`

` { x: 5, y: 10, isInside: false },`

` { x: 6, y: 1, isInside: false },`

` ]`

`};`

`getAvgInView(s) // 30.0`

Example CodePen:

Pass in a series of data, and it will average all the y values of all the points that are inside the viewport. Highcharts does that for me, but I have to actually make the average calculation.

Both of these examples take advantage of pure functions (none of these functions, composed or otherwise, mutate any data outside of the scope of the function), functional composition, and currying. By keeping these three concepts in mind, you should be able to convert a lot of your code into cleaner, functional code.

**Wrapping it all up**

I hope this introductory post was helpful for you to understand how functional programming works. To test your newfound knowledge, try to implement the map function and the filter function by using reduce. For simplicity, have your function take in an array rather than adding to the Array’s prototype, but you can do that as well.

`// all of these are valid`

`const myMap = (mapperFn, arr) => {`

` return arr.reduce(...)`

`}`

`const myMap2 = (arr, mapperFn) => {`

` return arr.reduce(...)`

`}`

`Array.prototype.myMap = function(mapperFn) {`

` return this.reduce(...)`

`}`

Remember the rule of pure functions. You cannot create intermediary variables and mutate them. There’s no need for functional composition or currying.

Good luck and happy coding!!

## Leave a Reply

Your email address will not be published. Required fields are marked *