Lambda – What is ‘Lambda’ in Programming?

lambda

What is this 'Lambda' everyone keeps speaking of? A lot of people seem to love it, but all I can gather from it is it is just a way of cramming lots of lines of code into a single expression.

Can someone please enlighten me on its true value?

Best Answer

Functions without a name

Simply put, a lambda is a function without a name, or an anonymous function. A small piece of executable code, that can be passed around as if it were a variable. In JavaScript:

function () {}; // very simple

Let's see now some uses for these lambdas.

Abstracting boilerplate code

Lambdas may be used to abstract away boilerplate code. For example loops. We're used to write for and while loops all day long. But this is code that does not be written. We could extract the code inside the loop, the most important part of the loop, and abstract away the rest:

for (var i=0; i<array.length; i++) {
    // do what something useful with array[i]
}

by using the forEach of array objects, becomes:

array.forEach(function (element, index) {
   // do something useful with element
   // element is the equivalent of array[i] from above
});

The above abstraction may not be that useful, but there are other higher order functions, like forEach, that perform much more useful tasks. For example filter:

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

// keep all even numbers from above array
for (var i=0; i<numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
        even.push(numbers[i]);
    }
}

alert(even);

// Using the filter method
even = [1, 2, 3, 4].filter(function (number) {
    return number % 2 === 0;
});

alert(even);

Code execution delay

In some environments, in which the concept of event is available, we could use lambdas to respond to events that may happen at some point in time.

window.onload = function () {
    alert("Loaded");
};

window.setTimeout(function () {
    alert("Code executed after 2 seconds.");
}, 2000);

This could have been done in some other ways, but those are rather verbose. For example, in Java there's the Runnable interface.

Factories of functions

Until this point, we only used lambdas for its syntactic sugar capabilities mostly. But there are situations where lambdas can be much more useful. For example we may have functions that return lambdas. Let's say we have a function that we want its return values to be cached.

var users = [];
var getUser = function (name) {
    if (! users[name]) {
        // expensive operations to get a user. Ajax for example
        users[name] = user_from_ajax;
    }

    return users[name];
};

Later on, we may notice that we have a similar function:

var photos = [];
var getPhoto = function (name) {
    if (! photo[name]) {
        // expensive operations to get a user. Ajax for example
        photos[name] = photo_from_ajax;
    }

    return photos[name];
};

There's clearly a pattern in there, so let's abstract it away. Let's use memoization.

/**
 * @param {Array}     store Data structure in which we cache lambda's return values
 * @param {Function}  lambda
 * @return {Function} A function that caches the result of calling the lambda param
 */
var memoize = function (store, lambda) {
    // return a new lambda
    return function (name) {
        if (! store[name]) {
            // Execute the lambda and cache the result
            store[name] = lambda(name);
        }

        return store[name];
    };
};

var getUsers = memoize([], function (name) {
    // expensive operations to get a user. Ajax for example
});

var getPhotos = memoize([], function (name) {
    // expensive operations to get a photo. Ajax for example
});

As you can see, by using lambdas, we were able to abstract away the caching/memoization logic. If for the other example there were some workarounds, I believe that this particular problem is hardly solved using other techniques. We managed to extract some important boilerplate code into a single place. Not to mention that we got rid of the users and photos global variables.

Looking at your profile I see that you're mostly a Python user. For the above pattern, Python has the concept of decorators. There are lots of example on the net for memoization decorators. The only difference is that in Python you most likely have a named nested function inside that decorator function. The reason being that Python only support single-expression lambdas. But the concept is the same.

As an example of Python lambda use. The above code in which we filtered even numbers can be represented in Python like this:

filter(lambda x: x % 2 == 0, [1, 2, 3, 4])

Anyway, lambdas are not that powerful without closures. Closures is what makes the concept of lambdas so powerful. In my memoization example I have used closures to create a closure around the store param. This way, I have access to that param even after the memoize function has returned its result (a lambda).