In the past two columns, we’ve looked at higher-order functions and talked a little bit about the power of functional programming. So far, the concepts we’ve covered do little to indicate how powerful the basic building blocks of functional programming are when combined. In this post, we’ll examine how functions alone can be used as data and data structures. This may sound strange, but you’ll soon see what I mean.
I first came across the concepts in this post in the excellent MIT course, Structure and Interpretation of Computer Programs, or SICP. The original recordings of the course lectures are available through MIT OpenCourseWare and I highly recommend them. In my professional life of programming, JavaScript was effectively my first programming language, but thanks to the SICP lectures, Scheme was my second.
Let’s begin with a rather silly example that sets a baseline. Consider a simple function called parrot
that takes an argument and returns the argument.
const parrot = (value) => {
return value;
};
parrot(1); // returns 1
parrot('Anything'); // returns 'Anything'
parrot(parrot); // returns the function parrot
This is known as the identity function. It is not very interesting but does illustrate that we can call a function with data and get data back immediately. What if we want to get data back later? When we think about storing data for later, we often turn to variables, which simply store data for later use. Could we use a function instead? It turns out that yes, we can, by modifying our parrot
function just a little. Instead of returning the value passed in immediately, we’ll return a function that returns the value.
const recall = (value) => {
return () => {
return value;
};
};const getValue = recall('My Value'); // This returns a function...
getValue(); // ...that when called, returns 'My Value'