views:

1740

answers:

5

Could someone explain? I understand the basic concepts behind them but I often see them used interchangeably and I get confused.

And now that we're here, how do they differ from a regular function?

+5  A: 

some good answers here.

What is a Lambda?

Gulzar
That's what I was looking for, should I delete this question?
sker
your question is a bit different. you are asking for differences between closure and lambda. keep it. :)
Gulzar
+10  A: 

Sorry for the confusion.

Not all closures are lambdas and not all lambdas are closures. Both are functions, but not necessarily in the manner we're used to knowing.

A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects.

A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure.

In an object-oriented language, closures are normally provided through objects. However, some OO languages (e.g. C#) implement special functionality that is closer to the definition of closures provided by purely functional languages (such as lisp) that do not have objects to enclose state.

What's interesting is that the introduction of Lambdas and Closures in C# brings functional programming closer to mainstream usage.

Mike Brown
So, could we say that closures are a subset of lambdas and lambdas are a subset of functions?
sker
Closures are a subset of lambdas...but lambdas are more special than normal functions.Like I said, lambdas are defined inline. Essentially there is no way to reference them unless they are passed to another function or returned as a return value.
Mike Brown
Lambdas and closures are each a subset of all functions, but there is only an intersection between lambdas and closures, where the non-intersecting part of closures would be named functions that are closures and non-intersecting lamdas are self-contained functions with fully-bound variables.
Mark Cidade
MikeBrown - can you please modify your answer? The statement "A closure is a lambda" is very misleading, as it definitely is NOT necessarily a lambda!
Claudiu
Thank you for setting me straight. I was a bit tired and lazy when I first answered.
Mike Brown
+21  A: 

When most people think of functions, they think of named functions:

function foo() { return "This string is returned from the 'foo' function"; }

These are called by name, of course:

foo(); //returns the string above

With lambda expressions, you can have anonymous functions:

 @foo = lambda() {return "This is returned from a function without a name";}

With the above example, you can call the lambda through the variable it was assigned to:

foo();

More useful than assigning anonymous functions to variables, however, are passing them to or from higher-order functions, i.e., functions that accept/return other functions. In a lot of these cases, naming a function is unecessary:

function filter(list, predicate) 
 { @filteredList = [];
   for-each (@x in list) if (predicate(x)) filteredList.add(x);
   return filteredList;
 }

//filter for even numbers
filter([0,1,2,3,4,5,6], lambda(x) {return (x mod 2 == 0)});

A closure may be a named or anonymous function, but is known as such when it "closes over" variables in the scope where the function is defined, i.e., the closure will still refer to the environment with any outer variables that are used in the closure itself. Here's a named closure:

@x = 0;

function incrementX() { x = x + 1;}

incrementX(); // x now equals 1

That doesn't seem like much but what if this was all in another function and you passed incrementX to an external function?

function foo()
 { @x = 0;

   function incrementX() 
    { x = x + 1;
      return x;
    }

   return incrementX;
 }

@y = foo(); // y = closure of incrementX over foo.x
y(); //returns 1 (y.x == 0 + 1)
y(); //returns 2 (y.x == 1 + 1)

This is how you get stateful objects in functional programming. Since naming "incrementX" isn't needed, you can use a lambda in this case:

function foo()
 { @x = 0;

   return lambda() 
           { x = x + 1;
             return x;
           };
 }
Mark Cidade
what language are you ising here?
Claudiu
It's basically pseudocode. There's some lisp and JavaScript in it, as well as a language I'm designing called "@" ("at"), named after the variable declaration operator.
Mark Cidade
Thanks, your answer made it more clear.
sker
+31  A: 

A lambda is just an anonymous function - a function defined with no name. In some languages, such as Scheme, they are equivalent to named functions. In fact, function definition is re-written as binding a lambda to a variable internally. In other languages, like Python, there are some (rather needless) distinctions between them, but they behave the same way otherwise.

A closure is any function which closes over the environment in which it was defined. This means that it can access variables not in its parameter list. Examples:

def func(): return h
def anotherfunc(h):
   return func()

This will cause an error, because func does not close over the environment in anotherfunc - h is undefined. func only closes over the global environment. This will work:

def anotherfunc(h):
    def func(): return h
    return func()

Because here, func is defined in anotherfunc, and in python 2.3 and greater (or some number like this) when they almost got closures correct (mutation still doesn't work), this means that it closes over anotherfunc's environment and can access variables inside of it.

Another important point - func will continue to close over anotherfunc's environment even when it's no longer being evaluated in anotherfunc. This code will also work:

def anotherfunc(h):
    def func(): return h
    return func

print anotherfunc(10)()

This will print 10.

This, as you notice, has nothing to do with lambda's - they are two different (although related) concepts.

Claudiu
Why the downvote?
Claudiu
Thanks, your answer made it more clear.
sker
Claudiu, to my uncertain knowledge python has never quite got closures correct. Did they fix the mutability problem while I wasn't looking? Quite possible...
simon
simon - you're right, they're still not fully correct. i think python 3.0 will add a hack to work around this. (something like a 'nonlocal' identifier). i'll change my ansewr to reflect that.
Claudiu
Good, clear answer!
David
This answer helped me a lot. Thank you.
avpx
+1  A: 

Theres actually a bug in lisp (its in the original definition) with regard to closures, finding the correct binding of a variable does not always work, heres the smallest example i can come up with:

(defun f (x) (lambda (x) (x)) 3) 5

this should evaluate to 3 but instead it evaluates to 5 because the inner x in the lambda is being bound by the argument to f not the argument to the lambda.

in scheme however it works as expected, here's a semantically identical definition in scheme:

(define (f x) (lambda (x) (x)) 3)
(f 5)

this evaluates (correctly) to 3, the scheme was evaluated by guile (gnu scheme) and the list by clisp

This isn't much of an answer but it does show that its not that easy to do right

luke
Downvoted because it is irrelevant.
Arafangion