8

I've spent an hour reading many posts on this site and others about lambdas and closures. I think I understand what they are, i.e. how they work, but I do not understand why they exist. Many examples I see refer vaguely to their "power," but in each of those cases I can think of a much simpler way to accomplish what is being illustrated. Maybe this is due to the examples being intentionally overly simple (for ease of understanding), or maybe I'm dense. But what I'd really like is to see a clear example of something you can accomplish with a closure or lambda that you can't accomplish without one. Maybe this is a loaded question, since all programming paradigms eventually boil down to the same machine instructions, and anything that can be done in one language can be done in another, somehow. So I guess what I'm really asking is for an example of something done with a closure that is more elegant than when done without (which does not seem to be the case for any example I've seen yet).

Here's what I'm talking about.

The leading answer for What is a 'Closure'? , an example in Scheme:

(define (make-counter)
  (let ((count 0))
    (lambda ()
      (set! count (+ count 1))
      count)))

(define x (make-counter))

(x) returns 1

(x) returns 2

...etc...

I don't know Scheme really, but I think I see what's going on. However, wouldn't this be more straightforward and accomplish the same thing? Pseudocode:

function incrementCount(var counter) {
    counter++;
    return counter;
}

counter = 1;
counter = incrementCount(counter);
counter = incrementCount(counter);

Here's another one on lambdas: What is a lambda (function)?

The JavaScript example given:

var adder = function (x) {
    return function (y) {
        return x + y;
    };
};
add5 = adder(5);
add5(1) == 6

Again, why do it that way? Why not just say:

function adder(x, y) {
    return x + y;
}
adder(5, 1);

Every example I've seen seems like an overly complicated way to do something that can easily be done with basic functions. These examples certainly don't illustrate any amazing cool "power" that I can see. So please, somebody enlighten me, I must be missing out on something. Thanks.

Community
  • 1
  • 1
The111
  • 5,757
  • 4
  • 39
  • 55
  • 1
    some good stuff here from a python POV. http://pythonconquerstheuniverse.wordpress.com/2011/08/29/lambda_tutorial/ – Paul Collingwood Dec 02 '12 at 10:27
  • 1
    lambdas are powerful because they can appear in expressions where as functions cannot. This allows you to use functions "inline" where it would not be practical or possible. For example, in Python this means for any sorting or iterative functions, the _key_ argument can be a function. – Burhan Khalid Dec 02 '12 at 10:28
  • Closures allow you to capture state implicitly. An example is the callback pattern: in C when you register a callback, the callback usually takes a parameter that contains an explicit state. Using closures, you just set a field to a closure, and you access the object's state in the closure. – ninjalj Dec 02 '12 at 10:48
  • The best example to quickly get the real power of currying is parsing combinators. Take a look at Parsec or any other similar implementation. – SK-logic Dec 02 '12 at 12:06
  • @PaulC thanks, that link was very helpful as far as explaining why lambdas are useful, and in fact I realize I've already used them in JavaScript before for the reasons stated there (GUI callback handlers)! – The111 Dec 02 '12 at 21:44

4 Answers4

5

Lambda calculus is actually pretty simple, and not that useful on its own. However it is when you start learning the implications of lambda calculus and strategies of application control using functional design patterns that you will become a better and more powerful programmer.

The premise is that functions are also values and this makes it really powerful for abstracting many concepts. Your two examples show the simplest way that closures and currying are implemented. Those are trivial examples. When you begin to program using a functional style, those pattern will come up over and over again as very powerful ways to abstract away complexity.

seperation of concerns

Functional programming is useful is when you start abstracting using higher order functions, the typical example being - I want to do something to a collection of objects.

so in an imperative program, you use a for loop:

result = Array(length);
for(i = 0; i < length; i++)
{
   result[i] = dosomething(input[i]);
}

notice that in the block of code, the dosomething function is right in the middle of the for loop. You can't really separate out what you are doing to each element of the array from the actual for-loop control structure.

However, by using a functional style, the control structure of the loop is abstracted away using map - a higher order function - you get clear separation of two concepts of looping and function application. This is the equivalent code in scheme.

(define result (map dosomething collection))

map takes care of the fact that you are traversing each element of the array. dosomething takes care of the fact that you are performing an operation on each element of the array. Reasoning about this becomes much more clear and changing the code becomes much easier. Now imagine that every for loop in your code was replaced by this construct and how many lines of code it will save.

cheap constructors

Addressing the concept of closures and currying. There is an equivalence between objects and functions. Essentially, functions can be made to look and behave like objects. Javascript makes great use of this fact. Anything you can do with objects, you can also do with functions. In fact, by getting rid of the distinction between what an object is and what a function is, you have effectively decluttered your mind and have one way of thinking about the problem - that is, through code that is built up through functionality.

I am using clojure code here because it is what i'm comfortable with:

This is the clojure code for trivial adder example, With the adder example, you are calling a addn with the number 5 to get back function that adds 5 to a number. a general use case may be:

(defn addn [n] (fn [m] (+ m n))
(def add5 (addn 5))

(map add5 [1 2 3 4 5 6])
;; => [6 7 8 9 10 11]

Say you had a function download-and-save-to that takes a url and a database, saves the url to a database table and returns true when it is successful, you can do exactly the same abstraction as you did with +:

(defn download-url-to [db]
  (fn [url] (download-and-save-to url db)))

(def download-url-mydb (download-url-to mydb))
(map download-url-mydb [url1 url2 url3 url4 url5])
;; => [true true false true true]

Notice that the structure is equivalent even though you are doing vastly different things. Think about how you would have approach this problem using java or c++. There would be a lot more code involved in class definitions, factory methods, class abstractions, inheritence.... essentially. you have to go through a whole lot more ceremony to get the same effect.

opening your mind

Because of the way you can express ideas so succinctly, functional programming can let you grasp many concepts that are very difficult to express in more verbose languages. The tool you pick will make exploring certain problems easier or harder.

I highly recommend clojure - (http://www.4clojure.com/) and lighttable - (http://www.lighttable.com/, http://www.kickstarter.com/projects/ibdknox/light-table) to get started. From my personal experience, my one year of learning and exploring concepts by the clojure community was akin to about 10 years of learning java, c++ and python combined.


Oh, did I mention how much fun I'm having learning all this stuff? Monads, combinators, propagators, continuations... all those scary looking academic concepts are actually well within reach when you have the right tools for understanding them.

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
zcaudate
  • 13,998
  • 7
  • 64
  • 124
  • I would not agree - lambda calculus is extremely useful on its own, since it is such a simple model which can be used to represent arbitrary complex semantics. You can embed on into your type system, you can reason about the code after transforming it into a pure lambda, etc. – SK-logic Dec 02 '12 at 12:03
  • Agreed =) though I'm not a computer so its harder for me to understand a program built strictly out of lambdas – zcaudate Dec 02 '12 at 12:07
  • you don't have to read/write a raw lambda. You can build upon higher levels of abstraction - use macros to add some syntax sugar: e.g., cons cells on top of Church pairs, decimal arithmetics on top of Church numbers, pattern matching, `cond` instead of lambda boolean functions, etc. And it is surprisingly easy to get a human readable, nice, high level language starting with nothing but a trivial, lazy lambda calculus. Several hundreds of lines of code, and you'll have a language much more powerful than, say, Java. – SK-logic Dec 02 '12 at 12:12
  • @zcaudate Thanks for the answer, some very deep mind opening perspectives in there. :-) I am beginning to see the light... – The111 Dec 02 '12 at 22:13
  • @The111 glad to be of service =) – zcaudate Dec 03 '12 at 07:13
  • Since you mention Python: all the examples that you give can be expressed in Python in essentially the same way as in Clojure (Python has `map()`, and functions are first-class objects). I'm curious about something that would be simple in Clojure and much heavier in Python. :) – Eric O. Lebigot Dec 05 '12 at 03:37
  • I remember choosing clojure after trying to write libraries in python and getting nowhere - mostly due to my lack of understanding of good design. The fact that there is no syntax in lisp lets me fit more ideas in my brain. You can definitely do everything in python... But sometimes it's better not to use some features unless you really have a need for it - like classes. Clojure has immutable data structures, features for multithreading right out of the box and makes the jvm a breeze to work with – zcaudate Dec 05 '12 at 23:42
4

This question is rather difficult to answer because you’ve already covered all your bases: You’ve already seen examples, descriptions, explanations — and you even realise that lambda expressions compile down into a machine language which itself doesn’t have lambda expressions as a primary feature.

Nonetheless, I am going to try giving one example which seems to be among the most common use-cases in which I, personally, use a lambda expression. I use C#, which is fundamentally an imperative language, but has lambda expressions as a built-in feature, so my examples will be in C#.

Imagine you have a function that needs a value. But this value is expensive to compute, so the requirements are:

  • If the function doesn’t need the value, it shall not be evaluated at all.
  • If the function needs the value multiple times, it shall be evaluated only once.

Lambda expressions make this very easy because you can use captured variables to “cache” the computed value:

bool computed = false;
MyType value = null;

var getValue = () => {
    if (!computed)
    {
        value = computeValue();    // this is the expensive operation
        computed = true;
    }
    return value;
};

Now I can pass getValue into any function, and no matter what this function does with it (i.e. how many times it calls it), I know that computeValue() will only be called once.

To do the same thing without a lambda, I would have to create a class equivalent to this lambda’s closure, and have it implement some sort of interface, for example:

sealed class Closure : IGetMyTypeValue
{
    bool Computed = false;
    MyType Value = null;

    public Closure() { }

    public MyType GetValue()   // implements IGetMyTypeValue.GetValue()
    {
        if (!Computed)
        {
            Value = ComputeValue();    // this is the expensive operation
            Computed = true;
        }
        return Value;
    }

    private MyType ComputeValue()
    {
        // expensive code goes here
    }
}

[...]

var closure = new Closure();
// pass closure to a method that expects an IGetMyTypeValue

The downsides of having to write this large class are:

  • You have to write a new class for every such expensive computation. This is very repetitive work; using lambda expressions allows the compiler to automate that.
  • You have to write a separate interface for every type of operation.
Timwi
  • 65,159
  • 33
  • 165
  • 230
  • You do not need a lambda to have `computeValue()` be called only once. Your example mostly rely on `getValue` being a closure (bound to the `computed` variable)—you can for instance do this in Python, without a lambda. – Eric O. Lebigot Dec 02 '12 at 10:45
  • @EOL: I don’t know Python well enough to reply to this. If you could show me the equivalent code in Python without lambdas, I could comment on it. Would you like to paste it somewhere and then link me to it? – Timwi Dec 02 '12 at 10:49
  • @EOL: sure. The nice thing about closures is that they solve some different problems in a uniform way, e.g: Timwi's example would be solved using `static` variables in C, and the callback problem (accessing relevant state from a callback) is solved in C by passing state explicitly. But using closures, they both are solved using a common idiom: the closure. – ninjalj Dec 02 '12 at 10:52
  • @Timwi: Here is a Python version of your code: http://pastebin.com/ycdsdxpV. It uses a simple, regular function definition, and not a lambda. (I'm taking lambda to mean "anonymous function", here, which may not be your intended meaning. :)) – Eric O. Lebigot Dec 02 '12 at 10:55
  • @EOL: Your code just uses **global variables**. That is not a closure and has a very different meaning. You cannot create an arbitrary number of those closures in your code; you are stuck with the finite set of globals you defined. – Timwi Dec 02 '12 at 11:39
  • @Timwi Thanks, that is a great example! So in the first example, the reason your closure is "sealed" is because you assigned it to a var rather than a function, correct? – The111 Dec 02 '12 at 21:51
  • @The111: No, the `sealed` has nothing to do with this. [It just means you can’t derive another class from it.](http://msdn.microsoft.com/en-us/library/88c54tsw.aspx) I habitually declare all classes `sealed` until I need to subclass them ① so that I don’t need to worry about the implications of it being subclassed until it is relevant, and ② because adding `sealed` later is a breaking change, but removing it is not (almost). – Timwi Dec 03 '12 at 06:50
  • @Timwi I think my choice of words was poor. When I said "sealed," I just meant "closed." I was referring to your **first** example, which does not have the word sealed in it. – The111 Dec 03 '12 at 07:03
  • @Timwi: You're right, the Python example indeed uses a global variable and is not really a closure. I just wanted to give the Python version of your code: I thought it too used a global variable (I have to guess what C# code does). :) That said, the Python code would work and be a closure if variables `computed` and `value` were local to, say, a function (Python 3, by replacing `global` with `nonlocal`): the `getValue()` function can be returned, and remain bound to the local variables (it's a closure). – Eric O. Lebigot Dec 05 '12 at 03:36
  • @EOL: Right, then the functionality is the same and the Python code is equivalent to the C# code. Whether you choose to call it a “lambda expression” or something else is immaterial; clearly, both provide the “power” that the OP was asking about. (To answer your implied question, C# doesn’t have global variables; the variables in my example were intended to be locals. I’m sorry that wasn’t clear because I omitted the surrounding method declaration.) – Timwi Dec 05 '12 at 20:54
2

I don't know if you are familiar with JavaScript, but closures and lambdas are a fundamental feature to simulate Object Oriented behavior.

Consider the following code:

var MyClass = function(buttonId) {
  var clickCounter = 0;

  var myButton = document.getElementById(buttonId);
  myButton.addEventListener(
    'onclick',
    function() {
      clickCounter += 1;
  });
};

var myButtonClickCounter = new MyClass();

In JavaScript there is nothing such as classes or private members, but we can create structures that act like them. Here is the code with the explanation of what it is doing:

// I define a class constructor that takes a string as an input parameter
var MyClass = function(buttonId) {
  // I define a private member called click
  var clickCounter = 0;

  // I get the reference to the button with the given id.
  var myButton = document.getElementById(buttonId);
  // I attach to it a function that will be triggered when you click on it.
  // The addEventListener method takes two arguments as input:
  //  - the name of the event
  //  - the function to be called when the event is triggered
  myButton.addEventListener(
    'onclick',
    function() {
      clickCounter += 1;
  });
};

// I create an instance of MyClass for a button called myButton
var myButtonClickCounter = new MyClass('myButton');

In this case, the function passed to the addEventListener method is a lambda function. Yes, you can always define it in some other way, but it's just implementation details. In this case, I could create another variable inside MyClass definition instead of the lambda function, like this:

var MyClass = function(buttonId) {
  var clickCounter = 0;

  var clickHandler = function() {
      clickCounter += 1;
  };

  var myButton = document.getElementById(buttonId);
  myButton.addEventListener(
    'onclick',
    clickHandler
  );
};

For what can I tell you about JavaScript, clickCounter is in that lambda function's closure scope, because it is defined in a function above its chain (MyClass), but clickHandler would also be present in that scope, not just clickCounter.

Assume that this class needs to create a listener to 4 different buttons, you would need to create a handler for each one, and every time one is triggered, all of the variables would be present in its closure scope. And having 8 variable references (4 handlers + 4 counters) is worse than just having the 4 counters.

Another advantage of having this closure, is that clickCounter is a private member of MyClass, because it is defined as a variable in its body and so it's not visible from outside. The clickHandler (even in its lambda function form), instead, is defined inside MyClass, so it will be able to reference it through the closure.

Edit: To make clickCounter somehow useful, imagine that you need a public method that tells you if the counter has reached a certain value. We can write it like this (at the bottom of the definition):

var MyClass = function(buttonId) {
  var clickCounter = 0;

  var myButton = document.getElementById(buttonId);
  myButton.addEventListener(
    'onclick',
    function() {
      clickCounter += 1;
  });

  // This method takes a value x as input, and returns
  // a boolean value, that tells you whether the button
  // has been clicked more than the given x.
  this.hasReached = function(x) {
    return (clickCounter >= x);
  };
};

// Somewhere else in your code...
var myButtonClickCounter = new MyClass('myButton');
...
if( myButtonClickCounter.hasReached(4) )
{
  // Do some great stuff
}

You could also have classical getter and setter that simply return or change the private variable's value, it depends on what you need. In this particular implementation I don't want to expose the private variable directly (and this is highly advised, because if the class is the only one that knows how to manipulate its members, the code is easier to maintain).

Note: keep in mind that this is just an example to show the usage of closures, there are more efficient ways to define classes in JavaScript!

4lbertoC
  • 233
  • 1
  • 6
  • Thanks, I like that example a lot, and I am familiar with JS so it is easy to ready and not too far off from some things I've done before. I understand the closure keeps the value of `clickCounter` alive and increments it with each click. But what syntax would we use to access (read) this value after it has accumulated some number of clicks? – The111 Dec 02 '12 at 22:20
  • 1
    I edited the answer and added an example of how you could use it, hope it helps! – 4lbertoC Dec 03 '12 at 22:30
0

Some of the other posted answers have referenced using closures to create private variables, but I think this example from John Resig's advanced JavaScript tutorial makes it much more clear. Perhaps someone else will benefit from it.

Source: http://ejohn.org/apps/learn/#54

function Ninja(){
  var slices = 0;

  this.getSlices = function(){
    return slices;
  };
  this.slice = function(){
    slices++;
  };
}

var ninja = new Ninja();
ninja.slice();

console.log(ninja.getSlices()); // 1!
console.log(slices); // undefined!
The111
  • 5,757
  • 4
  • 39
  • 55