Fundamentals of Functional Programming - Functional Programming in JavaScript (2015)

Functional Programming in JavaScript (2015)

Chapter 2. Fundamentals of Functional Programming

By now, you've seen a small glimpse of what functional programming can do. But what exactly is functional programming? What makes one language functional and not another? What makes one programming style functional and not another?

In this chapter, we will first answer these questions and then cover the core concepts of functional programming:

· Using functions and arrays for control flow

· Writing pure functions, anonymous functions, recursive functions, and more

· Passing functions around like objects

· Utilizing the map(), filter(), and reduce() functions

Functional programming languages

Functional programming languages are languages that facilitate the functional programming paradigm. At the risk of oversimplifying, we could say that, if a language includes the features required for functional programming, then it is a functional language—as simple as that. In most cases, it's the programming style that truly determines whether a program is functional or not.

What makes a language functional?

Functional programming cannot be performed in C. Functional programming cannot be performed in Java (without a lot of cumbersome workarounds for "almost" functional programming). Those and many more languages simply don't contain the constructs to support it. They are purely object-oriented and strictly non-functional languages.

At the same time, object-oriented programming cannot be performed on purely functional languages, such as Scheme, Haskell, and Lisp, just to name a few.

However, there are certain languages that support both models. Python is a famous example, but there are others: Ruby, Julia, and—here's the one we're interested in—JavaScript. How can these languages support two design patterns that are very different from each other? They contain the features required for both programming paradigms. However, in the case of JavaScript, the functional features are somewhat hidden.

But really, it's a little more involved than that. So what makes a language functional?

Characteristic

Imperative

Functional

Programming Style

Perform step-by-step tasks and manage changes in state

Define what the problem is and what data transformations are needed to achieve the solution

State Changes

Important

Non-existent

Order of Execution

Important

Not as important

Primary Flow Control

Loops, conditionals, and function calls

Function calls and recursion

Primary Manipulation Unit

Structures and class objects

Functions as first-class objects and data sets

The syntax of the language must allow for certain design patterns, such as an inferred type system, and the ability to use anonymous functions. Essentially, the language must implement Lambda calculus. Also, the interpreter's evaluation strategy should be non-strict and call-by-need (also known as deferred execution), which allows for immutable data structures and non-strict, lazy evaluation.

Advantages

You could say that the profound enlightenment you experience when you finally "get it" will make learning functional programming worth it. An experience such as this will make you a better programmer for the rest of your life, whether you actually become a full-time functional programmer or not.

But we're not talking about learning to meditate; we're talking about learning an extremely useful tool that will make you a better programmer.

Formally speaking, what exactly are the practical advantages of using functional programming?

Cleaner code

Functional programs are cleaner, simpler, and smaller. This simplifies debugging, testing, and maintenance.

For example, let's say we need a function that converts a two-dimensional array into a one-dimensional array. Using only imperative techniques, we could write it the following way:

function merge2dArrayIntoOne(arrays) {

var count = arrays.length;

var merged = new Array(count);

var c = 0;

for (var i = 0; i < count; ++i) {

for (var j = 0, jlen = arrays[i].length; j < jlen; ++j) {

merged[c++] = arrays[i][j];

}

}

return merged

}

And using functional techniques, it could be written as follows:

varmerge2dArrayIntoOne2 = function(arrays) {

return arrays.reduce( function(p,n){

return p.concat(n);

});

};

Both of these functions take the same input and return the same output. However, the functional example is much more concise and clean.

Modularity

Functional programming forces large problems to be broken down into smaller instances of the same problem to be solved. This means that the code is more modular. Programs that are modular are clearly specified, easier to debug, and simpler to maintain. Testing is easier because each piece of modular code can potentially be checked for correctness.

Reusability

Functional programs share a variety of common helper functions, due to the modularity of functional programming. You'll find that many of these functions can be reused for a variety of different applications.

Many of the most common functions will be covered later in this chapter. However, as you work as a functional programmer, you will inevitably compile your own library of little functions that can be used over and over again. For example, a well-designed function that searches through the lines of a configuration file could also be used to search through a hash table.

Reduced coupling

Coupling is the amount of dependency between modules in a program. Because the functional programmer works to write first-class, higher-order, pure functions that are completely independent of each other with no side effects on global variables, coupling is greatly reduced. Certainly, functions will unavoidably rely on each other. But modifying one function will not change another, so long as the one-to-one mapping of inputs to outputs remains correct.

Mathematically correct

This last one is on a more theoretical level. Thanks to its roots in Lambda calculus, functional programs can be mathematically proven to be correct. This is a big advantage for researchers who need to prove the growth rate, time complexity, and mathematical correctness of a program.

Let's look at Fibonacci's sequence. Although it's rarely used for anything other than a proof-of-concept, it illustrates this concept quite well. The standard way of evaluating a Fibonacci sequence is to create a recursive function that expresses fibonnaci(n) = fibonnaci(n-2) + fibonnaci(n–1)with a base case to return 1 when n < 2, which makes it possible to stop the recursion and begin adding up the values returned at each step in the recursive call stack.

This describes the intermediary steps involved in calculating the sequence.

var fibonacci = function(n) {

if (n < 2) {

return 1;

}

else {

return fibonacci(n - 2) + fibonacci(n - 1);

}

}

console.log( fibonacci(8) );

// Output: 34

However, with the help of a library that implements a lazy execution strategy, an indefinite sequence can be generated that states the mathematical equation that defines the entire sequence of numbers. Only as many numbers as needed will be computed.

var fibonacci2 = Lazy.generate(function() {

var x = 1,

y = 1;

return function() {

var prev = x;

x = y;

y += prev;

return prev;

};

}());

console.log(fibonacci2.length());// Output: undefined

console.log(fibonacci2.take(12).toArray());// Output: [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144]

var fibonacci3 = Lazy.generate(function() {

var x = 1,

y = 1;

return function() {

var prev = x;

x = y;

y += prev;

return prev;

};

}());

console.log(fibonacci3.take(9).reverse().first(1).toArray());// Output: [34]

The second example is clearly more mathematically sound. It relies on the Lazy.js library of JavaScript. There are other libraries that can help here as well, such as Sloth.js and wu.js. These will be covered in Chapter 3, Setting Up the Functional Programming Environment.

Functional programming in a nonfunctional world

Can functional and nonfunctional programming be mixed together? Although this is the subject of Chapter 7, Functional & Object-oriented Programming in JavaScript, it is important to get a few things straight before we go any further.

This book is not intended to teach you how to implement an entire application that strictly adheres to the rigors of pure functional programming. Such applications are rarely appropriate outside Academia. Rather, this book will teach you how to use functional programming design strategies within your applications to complement the necessary imperative code.

For example, if you need the first four words that only contain letters out of some text, they could naively be written like this:

var words = [], count = 0;

text = myString.split(' ');

for (i=0; count<4, i<text.length; i++) {

if (!text[i].match(/[0-9]/)) {

words = words.concat(text[i]);

count++;

}

}

console.log(words);

In contrast, a functional programmer might write them as follows:

var words = [];

var words = myString.split(' ').filter(function(x){

return (! x.match(/[1-9]+/));

}).slice(0,4);

console.log(words);

Or, with a library of functional programming utilities, they can be simplified even further:

var words = toSequence(myString).match(/[a-zA-Z]+/).first(4);

The key to identifying functions that can be written in a more functional way is to look for loops and temporary variables, such as words and count instances in the preceding example. We can usually do away with both temporary variables and loops by replacing them with higher-order functions, which we will explore later in this chapter.

Is JavaScript a functional programming language?

There is one last question we must ask ourselves. Is JavaScript a functional language or a non-functional language?

JavaScript is arguably the world's most popular and least understood functional programming language. JavaScript is a functional programming language in C-like clothing. Its syntax is undeniably C-like, meaning it uses C's block syntax and in-fix ordering. And it's one of the worst named languages in existence. It doesn't take a lot of imagination to see how so many people can confuse JavaScript as being related to Java; somehow, its name implies that it should be! But in reality it has very little in common with Java. And, to really cement the idea that JavaScript is an object-oriented language, libraries and frameworks such as Dojo and ease.js have been hard at work attempting to abstract it and make it suitable for object-oriented programming. JavaScript came of age in the 1990s when OOP was all the buzz, and we've been told that JavaScript is object-oriented because we want it to be so badly. But it is not.

Its true identity is much more aligned with its ancestors: Scheme and Lisp, two classic functional languages. JavaScript is a functional language, all the way. Its functions are first-class and can be nested, it has closures and compositions, and it allows for currying and monads. All of these are key to functional programming. Here are a few more reasons why JavaScript is a functional language:

· JavaScript's lexical grammar includes the ability to pass functions as arguments, has an inferred type system, and allows for anonymous functions, higher-order functions, closures and more. These facts are paramount to achieving the structure and behavior of functional programming.

· It is not a pure object-oriented language, with most object-oriented design patterns achieved by copying the Prototype object, a weak model for object-oriented programming. European Computer Manufacturers Association Script (ECMAScript), JavaScript's formal and standardized specifications for implementation, states the following in specification 4.2.1:

"ECMAScript does not contain proper classes such as those in C++, Smalltalk, or Java, but rather, supports constructors which create objects. In a class-based object-oriented language, in general, state is carried by instances, methods are carried by classes, and inheritance is only of structure and behavior. In ECMAScript, the state and methods are carried by objects, and structure, behavior and state are all inherited."

· It is an interpreted language. Sometimes called "engines", JavaScript interpreters often closely resemble Scheme interpreters. Both are dynamic, both have flexible datatypes that easily combine and transform, both evaluate the code into blocks of expressions, and both treat functions similarly.

That being said, it is true that JavaScript is not a pure functional language. What's lacking is lazy evaluation and built-in immutable data. This is because most interpreters are call-by-name and not call-by-need. JavaScript also isn't very good with recursion due to the way it handles tail calls. However, all of these issues can be mitigated with a little bit of attention. Non-strict evaluation, required for infinite sequences and lazy evaluation, can be achieved with a library called Lazy.js. Immutable data can be achieved simply by programming technique, but this requires more programmer discipline rather than relying on the language to take care of it. And recursive tail call elimination can be achieved with a method called Trampolining. These issues will be addressed in Chapter 6, Advanced Topics & Pitfalls in JavaScript.

Many debates have been waged over whether or not JavaScript is a functional language, an object-oriented language, both, or neither. And this won't be the last debate.

In the end, functional programming is way of writing cleaner code through clever ways of mutating, combining, and using functions. And JavaScript provides an excellent medium for this approach. If you really want to use JavaScript to its full potential, you must learn how to use it as a functional language.

Working with functions

Sometimes, the elegant implementation is a function. Not a method. Not a class. Not a framework. Just a function.

--John Carmack, lead programmer of the Doom video game

Functional programming is all about decomposing a problem into a set of functions. Often, functions are chained together, nested within each other, passed around, and treated as first-class citizens. If you've used frameworks such as jQuery and Node.js, you've probably used some of these techniques, you just didn't realize it!

Let's start with a little JavaScript dilemma.

Say we need to compile a list of values that are assigned to generic objects. The objects could be anything: dates, HTML objects, and so on.

var

obj1 = {value: 1},

obj2 = {value: 2},

obj3 = {value: 3};

var values = [];

function accumulate(obj) {

values.push(obj.value);

}

accumulate(obj1);

accumulate(obj2);

console.log(values); // Output: [obj1.value, obj2.value]

It works but it's volatile. Any code can modify the values object without calling the accumulate() function. And if we forget to assign the empty set, [], to the values instance then the code will not work at all.

But if the variable is declared inside the function, it can't be mutated by any rogue lines of code.

function accumulate2(obj) {

var values = [];

values.push(obj.value);

return values;

}

console.log(accumulate2(obj1)); // Returns: [obj1.value]

console.log(accumulate2(obj2)); // Returns: [obj2.value]

console.log(accumulate2(obj3)); // Returns: [obj3.value]

It does not work! Only the value of the object last passed in is returned.

We could possibly solve this with a nested function inside the first function.

var ValueAccumulator = function(obj) {

var values = []

var accumulate = function() {

values.push(obj.value);

};

accumulate();

return values;

};

But it's the same issue, and now we cannot reach the accumulate function or the values variable.

What we need is a self-invoking function.

Self-invoking functions and closures

What if we could return a function expression that in-turn returns the values array? Variables declared in a function are available to any code within the function, including self-invoking functions.

By using a self-invoking function, our dilemma is solved.

var ValueAccumulator = function() {

var values = [];

var accumulate = function(obj) {

if (obj) {

values.push(obj.value);

return values;

}

else {

return values;

}

};

return accumulate;

};

//This allows us to do this:

var accumulator = ValueAccumulator();

accumulator(obj1);

accumulator(obj2);

console.log(accumulator());

// Output: [obj1.value, obj2.value]

It's all about variable scoping. The values variable is available to the inner accumulate() function, even when code outside the scope calls the functions. This is called a closure.

Note

Closures in JavaScript are functions that have access to the parent scope, even when the parent function has closed.

Closures are a feature of all functional languages. Traditional imperative languages do not allow them.

Higher-order functions

Self-invoking functions are actually a form of higher-order functions. Higher-order functions are functions that either take another function as the input or return a function as the output.

Higher-order functions are not common in traditional programming. While an imperative programmer might use a loop to iterate an array, a functional programmer would take another approach entirely. By using a higher-order function, the array can be worked on by applying that function to each item in the array to create a new array.

This is the central idea of the functional programming paradigm. What higher-order functions allow is the ability to pass logic to other functions, just like objects.

Functions are treated as first-class citizens in JavaScript, a distinction JavaScript shares with Scheme, Haskell, and the other classic functional languages. This may sound bizarre, but all this really means is that functions are treated as primitives, just like numbers and objects. If numbers and objects can be passed around, so can functions.

To see this in action, let's use a higher-order function with our ValueAccumulator() function from the previous section:

// using forEach() to iterate through an array and call a

// callback function, accumulator, for each item

var accumulator2 = ValueAccumulator();

var objects = [obj1, obj2, obj3]; // could be huge array of objects

objects.forEach(accumulator2);

console.log(accumulator2());

Pure functions

Pure functions return a value computed using only the inputs passed to it. Outside variables and global states may not be used and there may be no side effects. In other words, it must not mutate the variables passed to it for input. Therefore, pure functions are only used for their returned value.

A simple example of this is a math function. The Math.sqrt(4) function will always return 2, does not use any hidden information such as settings or state, and will never inflict any side effects.

Pure functions are the true interpretation of the mathematical term for 'function', a relation between inputs and an output. They are simple to think about and are readily re-usable. Because they are totally independent, pure functions are more capable of being used again and again.

To illustrate this, compare the following non-pure function to the pure one.

// function that prints a message to the center of the screen

var printCenter = function(str) {

var elem = document.createElement("div");

elem.textContent = str;

elem.style.position = 'absolute';

elem.style.top = window.innerHeight/2+"px";

elem.style.left = window.innerWidth/2+"px";

document.body.appendChild(elem);

};

printCenter('hello world');

// pure function that accomplishes the same thing

var printSomewhere = function(str, height, width) {

var elem = document.createElement("div");

elem.textContent = str;

elem.style.position = 'absolute';

elem.style.top = height;

elem.style.left = width;

return elem;

};

document.body.appendChild(printSomewhere('hello world', window.innerHeight/2)+10+"px",window.innerWidth/2)+10+"px")

);

While the non-pure function relies on the state of the window object to compute the height and width, the pure, self-sufficient function instead asks that those values be passed in. What this actually does is allow the message to be printed anywhere, and this makes the function much more versatile.

And while the non-pure function may seem like the easier option because it performs the appending itself instead of returning an element, the pure function printSomewhere() and its returned value play better with other functional programming design techniques.

var messages = ['Hi', 'Hello', 'Sup', 'Hey', 'Hola'];

messages.map(function(s,i){

return printSomewhere(s, 100*i*10, 100*i*10);

}).forEach(function(element) {

document.body.appendChild(element);

});

Note

When the functions are pure and don't rely on state or environment, then we don't care about when or where they actually get computed. We'll see this later with lazy evaluation.

Anonymous functions

Another benefit of treating functions as first-class objects is the advent of anonymous functions.

As the name might imply, anonymous functions are functions without names. But they are more than that. What they allow is the ability to define ad-hoc logic, on-the-spot and as needed. Usually, it's for the benefit of convenience; if the function is only referred to once, then a variable name doesn't need to be wasted on it.

Some examples of anonymous functions are as follows:

// The standard way to write anonymous functions

function(){return "hello world"};

// Anonymous function assigned to variable

var anon = function(x,y){return x+y};

// Anonymous function used in place of a named callback function,

// this is one of the more common uses of anonymous functions.

setInterval(function(){console.log(new Date().getTime())}, 1000);

// Output: 1413249010672, 1413249010673, 1413249010674, ...

// Without wrapping it in an anonymous function, it immediately // execute once and then return undefined as the callback:

setInterval(console.log(new Date().getTime()), 1000)

// Output: 1413249010671

A more involved example of anonymous functions used within higher-order functions:

function powersOf(x) {

return function(y) {

// this is an anonymous function!

return Math.pow(x,y);

};

}

powerOfTwo = powersOf(2);

console.log(powerOfTwo(1)); // 2

console.log(powerOfTwo(2)); // 4

console.log(powerOfTwo(3)); // 8

powerOfThree = powersOf(3);

console.log(powerOfThree(3)); // 9

console.log(powerOfThree(10)); // 59049

The function that is returned doesn't need to be named; it can't be used anywhere outside the powersOf() function, and so it is an anonymous function.

Remember our accumulator function? It can be re-written using anonymous functions.

var

obj1 = {value: 1},

obj2 = {value: 2},

obj3 = {value: 3};

var values = (function() {

// anonymous function

var values = [];

return function(obj) {

// another anonymous function!

if (obj) {

values.push(obj.value);

return values;

}

else {

return values;

}

}

})(); // make it self-executing

console.log(values(obj1)); // Returns: [obj.value]

console.log(values(obj2)); // Returns: [obj.value, obj2.value]

Right on! A pure, high-order, anonymous function. How did we ever get so lucky? Actually, it's more than that. It's also self-executing as indicated by the structure, (function(){...})();. The pair of parentheses following the anonymous function causes the function to be called right away. In the above example, the values instance is assigned to the output of the self-executing function call.

Note

Anonymous functions are more than just syntactical sugar. They are the embodiment of Lambda calculus. Stay with me on this… Lambda calculus was invented long before computers or computer languages. It was just a mathematical notion for reasoning about functions. Remarkably, it was discovered that—despite the fact that it only defines three kinds of expressions: variable references, function calls, and anonymous functions—it was Turing-complete. Today, Lambda calculus lies at the core of all functional languages if you know how to find it, including JavaScript.

For this reason, anonymous functions are often called lambda expressions.

One drawback to anonymous functions remains. They're difficult to identify in call stacks, which makes debugging trickier. They should be used sparingly.

Method chains

Chaining methods together in JavaScript is quit common. If you've used jQuery, you've likely performed this technique. It's sometimes called the "Builder Pattern".

It's a technique that is used to simplify code where multiple functions are applied to an object one after another.

// Instead of applying the functions one per line...

arr = [1,2,3,4];

arr1 = arr.reverse();

arr2 = arr1.concat([5,6]);

arr3 = arr2.map(Math.sqrt);

// ...they can be chained together into a one-liner

console.log([1,2,3,4].reverse().concat([5,6]).map(Math.sqrt));

// parentheses may be used to illustrate

console.log(((([1,2,3,4]).reverse()).concat([5,6])).map(Math.sqrt) );

This only works when the functions are methods of the object being worked on. If you created your own function that, for example, takes two arrays and returns an array with the two arrays zipped together, you must declare it as a member of the Array.prototype object. Take a look at the following code snippet:

Array.prototype.zip = function(arr2) {

// ...

}

This would allow us to the following:

arr.zip([11,12,13,14).map(function(n){return n*2});

// Output: 2, 22, 4, 24, 6, 26, 8, 28

Recursion

Recursion is likely the most famous functional programming technique. If you don't know by now, a recursive function is a function that calls itself.

When a functions calls itself, something strange happens. It acts both as a loop, in that it executes the same code multiple times, and as a function stack.

Recursive functions must be very careful to avoid an infinite loop (rather, infinite recursion in this case). So just like loops, a condition must be used to know when to stop. This is called the base case.

An example is as follows:

var foo = function(n) {

if (n < 0) {

// base case

return 'hello';

}

else {

// recursive case

foo(n-1);

}

}

console.log(foo(5));

It's possible to convert any loop to a recursive algorithm and any recursive algorithm to a loop. But recursive algorithms are more appropriate, almost necessary, for situations that differ greatly from those where loops are appropriate.

A good example is tree traversal. While it's not too hard to traverse a tree using a recursive function, a loop would be much more complex and would need to maintain a stack. And that would go against the spirit of functional programming.

var getLeafs = function(node) {

if (node.childNodes.length == 0) {

// base case

return node.innerText;

}

else {

// recursive case:

return node.childNodes.map(getLeafs);

}

}

Divide and conquer

Recursion is more than an interesting way to iterate without for and while loops. An algorithm design, known as divide and conquer, recursively breaks problems down into smaller instances of the same problem until they're small enough to solve.

The historical example of this is the Euclidan algorithm for finding the greatest common denominator for two numbers.

function gcd(a, b) {

if (b == 0) {

// base case (conquer)

return a;

}

else {

// recursive case (divide)

return gcd(b, a % b);

}

}

console.log(gcd(12,8));

console.log(gcd(100,20));

So in theory, divide and conquer works quite eloquently, but does it have any use in the real world? Yes! The JavaScript function for sorting arrays is not very good. Not only does it sort the array in place, which means that the data is not immutable, but it is unreliable and inflexible. With divide and conquer, we can do better.

The merge sort algorithm uses the divide and conquer recursive algorithm design to efficiently sort an array by recursively dividing the array into smaller sub-arrays and then merging them together.

The full implementation in JavaScript is about 40 lines of code. However, pseudo-code is as follows:

var mergeSort = function(arr){

if (arr.length < 2) {

// base case: 0 or 1 item arrays don't need sorting

return items;

}

else {

// recursive case: divide the array, sort, then merge

var middle = Math.floor(arr.length / 2);

// divide

var left = mergeSort(arr.slice(0, middle));

var right = mergeSort(arr.slice(middle));

// conquer

// merge is a helper function that returns a new array

// of the two arrays merged together

return merge(left, right);

}

}

Lazy evaluation

Lazy evaluation, also known as non-strict evaluation, call-by-need and deffered execution, is an evaluation strategy that waits until the value is needed to compute the result of a function and is particularly useful for functional programming. It's clear that a line of code that states x = func() is calling for x to be assigned to the returned value by func(). But what x actually equates to does not matter until it is needed. Waiting to call func() until x is needed is known as lazy evaluation.

This strategy can result in a major increase in performance, especially when used with method chains and arrays, the favorite program flow techniques of the functional programmer.

One exciting benefit of lazy evaluation is the existence of infinite series. Because nothing is actually computed until it can't be delayed any further, it's possible to do this:

// wishful JavaScript pseudocode:

var infinateNums = range(1 to infinity);

var tenPrimes = infinateNums.getPrimeNumbers().first(10);

This opens the door for many possibilities: asynchronous execution, parallelization, and composition, just to name a few.

However, there's one problem: JavaScript does not perform Lazy evaluation on its own. That being said, there exist libraries for JavaScript that simulate lazy evaluation very well. That is the subject of Chapter 3, Setting Up the Functional Programming Environment.

The functional programmer's toolkit

If you've looked closely at the few examples presented so far, you'll notice a few methods being used that you may not be familiar with. They are the map(), filter(), and reduce() functions, and they are crucial to every functional program of any language. They enable you to remove loops and statements, resulting in cleaner code.

The map(), filter(), and reduce() functions make up the core of the functional programmer's toolkit, a collection of pure, higher-order functions that are the workhorses of the functional method. In fact, they're the epitome of what a pure function and what a higher-order function should be like; they take a function as input and return an output with zero side effects.

While they're standard for browsers that implement ECMAScript 5.1, they only work on arrays. Each time it's called, a new array is created and returned. The existing array is not modified. But there's more, they take functions as inputs, often in the form of anonymous functions referred to as callback functions; they iterate over the array and apply the function to each item in the array!

myArray = [1,2,3,4];

newArray = myArray.map(function(x) {return x*2});

console.log(myArray); // Output: [1,2,3,4]

console.log(newArray); // Output: [2,4,6,8]

One more thing. Because they only work on arrays, they do not work on other iterable data structures, like certain objects. Fret not, libraries such as underscore.js, Lazy.js, stream.js, and many more all implement their own map(), filter(), and reduce() methods that are more versatile.

Callbacks

If you've never worked with callbacks before, you might find the concept a little puzzling. This is especially true in JavaScript, given the several different ways that JavaScript allows you to declare functions.

A callback() function is used for passing to other functions for them to use. It's a way to pass logic just as you would pass an object:

var myArray = [1,2,3];

function myCallback(x){return x+1};

console.log(myArray.map(myCallback));

To make it simpler for easy tasks, anonymous functions can be used:

console.log(myArray.map(function(x){return x+1}));

They are not only used in functional programming, they are used for many things in JavaScript. Purely for example, here's a callback() function used in an AJAX call made with jQuery:

function myCallback(xhr){

console.log(xhr.status);

return true;

}

$.ajax(myURI).done(myCallback);

Notice that only the name of the function was used. And because we're not calling the callback and are only passing the name of it, it would be wrong to write this:

$.ajax(myURI).fail(myCallback(xhr));

// or

$.ajax(myURI).fail(myCallback());

What would happen if we did call the callback? In that case, the myCallback(xhr) method would try to execute—'undefined' would be printed to the console and it would return True. When the ajax() call completes, it will have 'true' as the name of the callback function to use, and that will throw an error.

What this also means is that we cannot specify what arguments are passed to the callback functions. If we need different parameters from what the ajax() call will pass to it, we can wrap the callback function in an anonymous function:

function myCallback(status){

console.log(status);

return true;

}

$.ajax(myURI).done(function(xhr){myCallback(xhr.status)});

Array.prototype.map()

The map() function is the ringleader of the bunch. It simply applies the callback function on each item in the array.

Note

Syntax: arr.map(callback [, thisArg]);

Parameters:

· callback(): This function produces an element for the new array, receiving these arguments:

o currentValue: This argument gives the current element being processed in the array

o index: This argument gives the index of the current element in the array

o array: This argument gives the array being processed

· thisArg(): This function is optional. The value is used as this when executing callback.

Examples:

var

integers = [1,-0,9,-8,3],

numbers = [1,2,3,4],

str = 'hello world how ya doing?';

// map integers to their absolute values

console.log(integers.map(Math.abs));

// multiply an array of numbers by their position in the array

console.log(numbers.map(function(x, i){return x*i}) );

// Capitalize every other word in a string.

console.log(str.split(' ').map(function(s, i){

if (i%2 == 0) {

return s.toUpperCase();

}

else {

return s;

}

}) );

Note

While the Array.prototype.map method is a standard method for the Array object in JavaScript, it can be easily extended to your custom objects as well.

MyObject.prototype.map = function(f) {

return new MyObject(f(this.value));

};

Array.prototype.filter()

The filter() function is used to take elements out of an array. The callback must return True (to include the item in the new array) or False (to drop it). Something similar could be achieved by using the map() function and returning a null value for items you want dropped, but the filter()function will delete the item from the new array instead of inserting a null value in its place.

Note

Syntax: arr.filter(callback [, thisArg]);

Parameters:

· callback(): This function is used to test each element in the array. Return True to keep the element, False otherwise. With these parameters:

o currentValue: This parameter gives the current element being processed in the array

o index: This parameter gives the index of the current element in the array

· array: This parameter gives the array being processed.

· thisArg(): This function is optional. Value is used as this when executing callback.

Examples:

var myarray = [1,2,3,4]

words = 'hello 123 world how 345 ya doing'.split(' ');

re = '[a-zA-Z]';

// remove all negative numbers

console.log([-2,-1,0,1,2].filter(function(x){return x>0}));

// remove null values after a map operation

console.log(words.filter(function(s){

return s.match(re);

}) );

// remove random objects from an array

console.log(myarray.filter(function(){

return Math.floor(Math.random()*2)})

);

Array.prototype.reduce()

Sometimes called fold, the reduce() function is used to accumulate all the values of the array into one. The callback needs to return the logic to be performed to combine the objects. In the case of numbers, they're usually added together to get a sum or multiplied together to get a product. In the case of strings, the strings are often appended together.

Note

Syntax: arr.reduce(callback [, initialValue]);

Parameters:

· callback(): This function combines two objects into one, which is returned. With these parameters:

o previousValue: This parameter gives the value previously returned from the last invocation of the callback, or the initialValue, if supplied

o currentValue: This parameter gives the current element being processed in the array

o index: This parameter gives the index of the current element in the array

o array: This parameter gives the array being processed

· initialValue(): This function is optional. Object to use as the first argument to the first call of the callback.

Examples:

var numbers = [1,2,3,4];

// sum up all the values of an array

console.log([1,2,3,4,5].reduce(function(x,y){return x+y}, 0));

// sum up all the values of an array

console.log([1,2,3,4,5].reduce(function(x,y){return x+y}, 0));

// find the largest number

console.log(numbers.reduce(function(a,b){

return Math.max(a,b)}) // max takes two arguments

);

Honorable mentions

The map(), filter(), and reduce() functions are not alone in our toolbox of helper functions. There exist many more functions that can be plugged into nearly any functional application.

Array.prototype.forEach

Essentially the non-pure version of map(), forEach() iterates over an array and applies a callback() function over each item. However, it doesn't return anything. It's a cleaner way of performing a for loop.

Note

Syntax: arr.forEach(callback [, thisArg]);

Parameters:

· callback(): This function is to be performed for each value of the array. With these parameters:

o currentValue: This parameter gives the current element being processed in the array

o index: This parameter gives the index of the current element in the array

o array: This parameter gives the array being processed

· thisArg: This function is optional. Value is used as this when executing callback.

Examples:

var arr = [1,2,3];

var nodes = arr.map(function(x) {

var elem = document.createElement("div");

elem.textContent = x;

return elem;

});

// log the value of each item

arr.forEach(function(x){console.log(x)});

// append nodes to the DOM

nodes.forEach(function(x){document.body.appendChild(x)});

Array.prototype.concat

When working with arrays instead of for and while loops, often you will need to join multiple arrays together. Another built-in JavaScript function, concat(), takes care of this for us. The concat() function returns a new array and leaves the old arrays untouched. It can join as many arrays as you pass to it.

console.log([1, 2, 3].concat(['a','b','c']) // concatenate two arrays);

// Output: [1, 2, 3, 'a','b','c']

The original array is untouched. It returns a new array with both arrays concatenated together. This also means that the concat() function can be chained together.

var arr1 = [1,2,3];

var arr2 = [4,5,6];

var arr3 = [7,8,9];

var x = arr1.concat(arr2, arr3);

var y = arr1.concat(arr2).concat(arr3));

var z = arr1.concat(arr2.concat(arr3)));

console.log(x);

console.log(y);

console.log(z);

Variables x, y and z all contain [1,2,3,4,5,6,7,8,9].

Array.prototype.reverse

Another native JavaScript function helps with array transformations. The reverse() function inverts an array, such that the first element is now the last and the last is now the first.

However, it does not return a new array; instead it mutates the array in place. We can do better. Here's an implementation of a pure method for reversing an array:

var invert = function(arr) {

return arr.map(function(x, i, a) {

return a[a.length - (i+1)];

});

};

var q = invert([1,2,3,4]);

console.log( q );

Array.prototype.sort

Much like our map(), filter(), and reduce() methods, the sort() method takes a callback() function that defines how the objects within an array should be sorted. But, like the reverse() function, it mutates the array in place. And that's no bueno.

arr = [200, 12, 56, 7, 344];

console.log(arr.sort(function(a,b){return a–b}) );

// arr is now: [7, 12, 56, 200, 344];

We could write a pure sort() function that doesn't mutate the array, but sorting algorithms is the source of much grief. Significantly large arrays that need to be sorted really should be organized in data structures that are designed just for that: quickStort, mergeSort, bubbleSort, and so on.

Array.prototype.every and Array.prototype.some

The Array.prototype.every() and Array.prototype.some() functions are both pure and high-order functions that are methods of the Array object and are used to test the elements of an array against a callback() function that must return a Boolean representing the respective input. Theevery() function returns True if the callback() function returns True for every element in the array, and the some() function returns True if some elements in the array are True.

Example:

function isNumber(n) {

return !isNaN(parseFloat(n)) && isFinite(n);

}

console.log([1, 2, 3, 4].every(isNumber)); // Return: true

console.log([1, 2, 'a'].every(isNumber)); // Return: false

console.log([1, 2, 'a'].some(isNumber)); // Return: true

Summary

In order to develop an understanding of functional programming, this chapter covered a fairly broad range of topics. First we analyzed what it means for a programming language to be functional, then we evaluated JavaScript for its functional programming capabilities. Next, we applied the core concepts of functional programming using JavaScript and showcased some of JavaScript's built-in functions for functional programming.

Although JavaScript does have a few tools for functional programming, its functional core remains mostly hidden and much is to be desired. In the next chapter, we will explore several libraries for JavaScript that expose its functional underbelly.