Higher Order Functions

Closures, function factories, common factory pattern functions

In the first chapter we saw first class functions, ie. functions as first class citizens of the language. Higher order functions are functions that do one of the following

  • Take a function as one of its arguments
  • Returns a function

A function is said to be functional if it takes a function as its argument. Higher order functions form the backbone of functional programming.

Creating Closures

Mastering closures is the key to mastering JavaScript, and functional JavaScript. Closures are every where in JavaScript, and you would not be able to do very much in a functional manner without closures. Let us look at an example.

var showName = function() {
var name = “FP JavaScript”
return function() {
console.log(name)
}
}()
showName() //==>> FP JavaScript
console.log(name) //==>> Reference Error

We created an immediately executed anonymous function.

function() {
}()

And assigned its return value to showName. showName is set to the function.

function() {
console.log(name)
}

We also created a variable name in the same scope as the above function. The variable is visible inside the function, as the function prints its value.

Outside the immediately executed function, name is undefined. We get an error when we try to access it. However we can print the name calling showName. Even though the function which created name has run and returned, name continues to be accessible inside showName.

In effect we created a closure with a variable name for the function showName. You can do whatever you want with showName. Pass it to another function, or where ever you want. You can bank on its closure to faithfully follow it.

A functions closure is a pointer, that the function carries with it. It points to a table of all the variables in the scope where the function was created.

A closure is created every time a function returns another function defined within it.

Creating closures should come naturally to a JavaScript programmer. If not, keep practising closures. We will be making a lot of closures in this book. You should recognise them even if it is not always explicitly mentioned.

Function Factory

Consider the code below.

function add(x) {
return function(y) {
return x + y
}
}
var add2 = add(2)
var add3 = add(3)
add2(4) //==>> 6
add3(6) //==>> 9

The function add takes a single variable x and returns a function, which in turn takes a single variable y and returns the sum of x and y.

add is a Function Factory. Given a value, it creates a function, that adds a given value to a value stored in its closure.

So why not just write add as add(x, y)? This is surely simpler. Writing functions as function factories allow you to compose other functions. We will see more of this below. And in the chapter on composition.

We will look at some of the common functions that are written using the function factory pattern.

get

function get(prop) {
return function(obj) {
return obj[prop]
}
}

What is interesting about this function is that it does no “getting” so to speak. It just returns another function.

var getName = get(“name”)

getName gets set to a function returned by get. But before returning anything, get creates a closure with variable prop (property) for getName. And the property is set to “name”.

var book = {
name: “FP JavaScript”
}
getName(book) //==>> FP JavaScript

get can be used with arrays too.

get(1)([1, 2, 3]) //==>> 2

This is the way get works in functional languages. This is useful when you compose it with other functions. Also useful if you are accessing the same property of a set of objects. We will see all this in action next.

map

We will rewrite the JavaScript array map function in a functional manner.

function map(fn) {
return function(arr) {
return Array.prototype.map.call(arr, fn)
}
}
map(function(x) {return x * x}) ([1, 2, 3]) //==>> [ 1, 4, 9 ]

Notice that the arguments are flipped. The function comes first then the array. Also we used Array.prototype.map.call instead of just calling arr.map. This is so that we can use our map function with array like objects, arguments and DOMNodeList.

Say you wanted to get all the emails from a list like this in an array.

var people = [ {name:”John”, email:”john@example.com”},
{name:”Bill”, email:”bill@example.com”} ]
map(get(‘email’)) (people)
//===>> [ ‘john@example.com’, ‘bill@example.com’ ]

You see the advantage of writing get this way. You can pass it as an argument to another function. We composed get with map. Next we will see the advantage of writing map this way.

pluck

The pattern map(get()) we saw above is so common that we a have a function for it called pluck.

function pluck(prop) {
return map(get(prop))
}
pluck(‘email’)(people)
//===>> [ ‘john@example.com’, ‘bill@example.com’ ]

pluck is a function composition of map and get(prop). Composition works from right to left.

map returns a function that requires an array. But has also set its required function get(prop) in its closure.

So pluck(‘email’) is a function returned by map. Now we need to call it with array to evaluate it. map then calls the arrays map function with the function in its closure.

forEach

function forEach(fn) {
return function(arr) {
Array.prototype.forEach.call(arr, fn)
}
}

This works just like our map function earlier, except that it just iterates over an array, and does not return anything. This will also work with a DOMNodeList.

A common pattern we encounter often while doing client side development is iteration over a NodeList returned by document.querySelectorAll. To accomplish this we can write a generic higher order function to iterate over a NodeList given a selector.

<!DOCTYPE html><html><body>
<div>Hide Me</div>
<div>Hide Me Too</div>
<script>
function forEach(fn) {
return function(arr) {
Array.prototype.forEach.call(arr, fn)
}
}
var displayNone = forEach(function(elem) {
elem.style.display = “none”
})
displayNone(document.querySelectorAll(“div”))
</script>
</body></html>

take

take takes a number n and returns a function, to which you must pass an array, to get the first n elements of the array.

function take(n) {
return function(arr) {
return arr.slice(0, n)
}
}

flip

flip takes a function of two or more arguments and returns a function with the first two arguments flipped.

function flip(fn) {
return function(first, second) {
var rest = [].slice.call(arguments, 2)
return fn.apply(null, [second, first].concat(rest))
}
}

flip is useful when you need to partially apply a given function in the order you want the arguments. We will learn more about partial application in the chapter on currying.

memoize

Memoization is the process in which a function caches its results, and returns results from the cache, if the function was called before with the same argument(s).

function memoize(fn) {
var cache = {}
return function(arg) {
return (arg in cache) ? cache[arg] : (cache[arg] = fn(arg))
}
}

This is memoize for a function that takes one argument. It returns a function with an object cache in its closure. Every time the function is called it checks the cache for the argument. If found it returns the corresponding value. Otherwise it sets the cache with the argument and result, and returns the result.

memoize is very useful to optimise lengthy calculations, or expensive recursive operations.

The fibonacci series calculation is the popular example used to demonstrate the memoize function. Because the computation involved grows exponentially the larger the number you want to calculate in the series.

Each number in the fibonacci series is the sum of the previous two numbers starting after the second number. eg. 1,1,2,3,5,8,13,21 .. etc. And we can write this as

function fib(n) {
return n < 2 ? 1 : fib(n — 1) + fib(n — 2)
}

And let us run some tests.

var fibmemo = memoize(fib)
var start = new Date()
fibmemo(20)
console.log(new Date() — start) //==>> 11 ms on my machine
start = new Date()
fibmemo(20)
console.log(new Date() — start) //==>> 0 ms

Notice that running fibmemo(20) the second time round took only 0 ms, because it just returned the cached value.

We need to modify memoize to handle functions with multiple arguments. Fortunately that is quite simple.

function memoize(fn) {
var cache = {}
return function() {
var args = Array.prototype.slice.call(arguments)
return (args in cache) ? cache[args] :
(cache[args] = fn.apply(null, args))
}
}

First we convert the arguments passed to an array in args. Since args is an array and is used in the context of a object key (hash), it will be coerced into a string. Second, we now apply the array to fn.

once

once will create a function you can only run once. Subsequent invocations will return the first result.

function once(fn) {
var cache = {}
return function() {
return (“once” in cache) ? cache[“once”] :
(cache[“once”] = fn.apply(null, arguments))
}
}