Functional Javascript
Functional programming is seeing an increase in popularity, as can be seen in rising adoption of languages like Scala, Clojure and Erlang. Even Java has introduced lambdas (more about lambdas, later).
Javascript supports a functional programming style and I find that working within that style makes many things simpler when developing Javascript. This is particularly true when working with promises.
This blog entry discusses some basic functional techniques and demonstrates how they can be used within Javascript. It should be useful to both people who wish to adopt a more functional style in their Javascript, and to people who just want to understand more about functional programming.
What is Functional Programming?
Functional programming is an approach where a program consists of a series of transformations of data, achieved by repeatedly applying functions (or expressions) to arrive at a result.
Functional programming was the approach behind some of the earliest computer languages (like lisp), but lost popularity as more procedural (e.g. Algol, C) and then object-oriented (e.g. C++, Java) became dominant. However, as I stated at the start, in recent times there has been a resurgence in popularity of functional languages.
We should also note that in some areas, functional programming has never gone away. To some degree Excel formulas, SQL expressions and XSLT transformations are all functional programming.
Functional programming has a long history, since it is based on lambda calculus — a mathematical system of logic constructed in the 1930s. This is why we refer to lambda functions in some programming languages (e.g. the lambdas introduced in Java 8).
Lambda calculus is responsible for the fundamental concepts and terminology of functional programming. Two examples are anonymous functions and currying. We will discuss both later as part of functional programming, but if you are interested in the formal lambda calculus basis for functional programming, there is a fairly readable description on wikipedia.
Functional vs Procedural Programming
The basic difference between functional and procedural (or object-oriented) programming is that functional programming states what needs to be done (declarative), whereas procedural programming states how to do it (imperative).
As an example of this, suppose that we have an array of numbers. We want to subtract 2 from every element in the array and then only keep those elements which are positive. The following code gives a procedural and a functional way of doing this:
// An array of data to work with
var inputData = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3];
console.log("Input data: ", inputData);
// === Example of a procedural approach ====================
var result1 = [];
for (var i = 0; i < inputData.length; i++) {
var n = inputData[i] - 2;
if (n > 0) {
result1.push(n);
}
}
console.log("Result (procedural):", result1);
// === Example of a functional approach ====================
// Subtract 2 from a number
function sub2 (n) {
return n - 2;
}
// Is a number positive?
function isPositive (n) {
return n > 0;
}
// Calculate result
var result2 = inputData
.map(sub2)
.filter(isPositive);
console.log("Result (functional):", result2);
And here is the output showing that both approaches give the same result:
Input data: [ 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 ]
Result (procedural): [ 1, 2, 3, 7, 4, 3, 1 ]
Result (functional): [ 1, 2, 3, 7, 4, 3, 1 ]
As you can see from the example, the procedural version (as the name suggests) gives a process which needs to be followed to arrive at the result. It could be read as “take each item in the array, subtract 2 from it and if the result is greater than zero, add it to our result”.
The functional version, on the other hand, specifies the transformations which need to be applied. It could be read as “subtract 2 from each element of the array, then keep any which are positive”.
Note that the functional version does not specify an evaluation order — we do not know from the code in which order the subtraction will be applied to the array. In actual fact, Javascript defines this order (from start to end), but there are some places where the order is genuinely not known. MongoDB’s map-reduce is an example of this. The evaluation can be distributed across multiple MongoDB servers and the order of that evaluation cannot be predicted in advance. To support this, we need to write so-called pure functions — more about them when we talk about memoization.
Another thing which you may have noticed is that we have passed one function (sub2) into another function (map). This is a fundamental feature of functional programming and we will now look at this in more detail.
Functions are First Class
We can define a function in Javascript, the same way as we do in other languages. For example, here is an increment function:
// Example function to increment argument
function inc (n) {
return n + 1;
}
We then call it in the standard way:(0)
// Expression
inc(100)
// Result
101
However, in Javascript a function is a first order entity. This means that it is a Javascript object which can be treated in the same way as any other object in Javascript.
For example, we can evaluate it to see its value:
// Expression
inc
// Result
[Function: inc]
Since a function is a Javascript object, it also inherits the functions defined
on the generic object. So, for example, it has a toString()
function (which
displays the definition of the function):
// Expression
inc.toString()
// Result
function inc(n) {
return n + 1;
}
Since a function is an object, we can also set attributes on it:
// Expression
inc.foo = "xyzzy"
// Result
xyzzy
// Expression
inc
// Result
{ [Function: inc] foo: 'xyzzy' }
As I mentioned at the start, functional programming is based on lambda calculus
and one of key concepts there is the anonymous function. As the name
suggests, this is a function without a name. In Javascript, to define an
anonymous function we simply leave out the function name between the keyword
function
and the argument list.
Here is an example of a decrement function defined using the anonymous function syntax. Note that we assign the function to a variable so we can call it, but the actual function definition does not specify a name:
// Example anonymous function
var dec = function (n) {
return n - 1;
}
We call it like any other function and it behaves as expected:
dec(100)
// Result
99
We can display its value, just like we did before, but note that because it is
an anonymous function, this time there is no name associated with the function
(compare the output from this command to the earlier example for our inc
function):
// Expression
dec
// Result
[Function: dec]
Another thing we can do with Javascript objects is return them as the result of a function. Since a function is an object, we can therefore return one function as the result of calling another.
Here is an example of a function called op
, which takes as an argument either
+1
or -1
. If the argument is +1
it returns our inc
function, whereas
if the argument is -1
it returns our dec
function:
// Return a function from a function
function op (type) {
if (type === "+1") {
return inc;
}
if (type === "-1") {
return dec;
}
return null;
}
~~
Let's just start by checking that `op` is a standard function:
~~~text
// Expression
op
// Result
[Function: op]
We can now call it with +1
and check that it does return our inc
function:
// Expression
op("+1")
// Result
[Function: inc]
Because this result is our original inc
function, we can call it just like we
would any other function — by providing arguments in brackets:
// Expression
op("+1")(1000)
// Result
1001
// Expression
op("-1")(1000)
// Result
999
We can also pass a function into another function as a parameter (just as we
can pass any object into a function). Here is a simple example of that, a
function which will call the passed in function with the number 50
as its
argument:
// Pass a function into a function
function with50 (fn) {
return fn(50);
}
This behaves as expected when we pass in our inc
and dec
functions as the
parameter:
// Expression
with50(inc)
// Result
51
// Expression
with50(dec)
// Result
49
This is the same principle that we used earlier to pass the sub2
function
into the map
function. It is a powerful technique, which we will be making
extensive use of throughout these blog entries.
We can also define anonymous functions as values in objects. This is an important pattern, since it allows namespacing of functions and is also a building block for structures in frameworks such as AngularJS:
var maths = {
inc: function (n) {
return n + 1;
},
dec: function (n) {
return n - 1;
}
};
Here is what the structure looks like (containing our two functions):
// Expression
maths
// Result
{ inc: [Function: inc], dec: [Function: dec] }
We can then call these functions using standard object dot notation:
// Expression
maths.inc(10)
// Result
11
// Expression
maths.dec(10)
// Result
9
Closures
Another important element of function programming are closures. Wikipedia describes closures in the following way:
In programming languages, closures (also lexical closures or function closures) are a technique for implementing lexically scoped name binding in languages with first-class functions.
So what does that mean?
The way I think of it is that a closure lets us access variables which were in scope when the function was created — even if those variables seem to be out of scope when the function is called.
An example should make this clearer:
// Example of a closure
function closureDemo () {
var x = 100;
return {
get: function () {
return x;
},
set: function (n) {
x = n;
return true;
}
};
}
What we have done here is create a function (closureDemo) which returns an object. That object contains two functions itself (get and set). There is also a variable defined locally to closureDemo (called x) which is referenced in the get and set functions.
We now call our closureDemo function and store the result in a variable called demo:
// Expression
demo = closureDemo()
// Result
{ get: [Function: get], set: [Function: set] }
If we look at the object we have just created, as expected it contains the two functions get and set:
~~#text // Expression demo
// Result { get: [Function: get], set: [Function: set] }
Our variable *x* was defined locally to *closureDemo*, so it is nowhere to be
seen. If we look for it in our object, we can confirm that it's not there:
~~~text
// Expression
demo.x
// Result
undefined
This is all as we would have predicted, but look at what happens when we call our get function:
// Expression
demo.get()
// Result
100
Our local variable x from our closureDemo function is still available for our get function to read and it returns the value which was assigned to it as a local variable.
This is an example of a closure in action. Because x had a definition at the time our get function was defined, it is still available to that get function.
Not only can we read our variable, we can also modify it, because our set function is also a closure which has access to x:
// Expression
demo.set(75)
// Result
true
// Expression
demo.get()
// Result
75
For those of you from an object-oriented background, this may look familiar - our variable x is acting like a private variable. It can’t be modifed directly, only via functions. This is a common Javascript pattern and can also be used to create private functions; a technique popularised by Douglas Crockford.
Summary
This blog post has given an introduction to functional programming in Javascript, covering the fact that functions are first order entities; how we can use them as we do any other object; and describing closures.
The next blog entry will look at curried functions and partial application of functions.