62

Are lambda expressions (and to a degree, anonymous functions) closures?

My understanding of closures are that they are functions that are treated as objects, which seems to be an accurate representation of what anonymous functions and Lambda expressions do.

And is it correct to call them closures? I understand that closures came about (or became popular) due to the lisp dialect, but is it also a general programming term?

Thanks for any clarification that you can provide!

Dan J
  • 16,319
  • 7
  • 50
  • 82
Stefan H
  • 6,635
  • 4
  • 24
  • 35
  • 5
    NB they're called closures. "Clojure" is a language (hence my edit). – Daniel Earwicker Mar 06 '12 at 20:41
  • Ah - that definitely clears up that confusion! Thanks – Stefan H Mar 06 '12 at 20:42
  • Closures are an aspect of lambda expressions. Lambdas need not necessarily support closures. Some languages implement it differently. For eg, Java is different from C# in that former doesn't allow modification of closed over variable within the function. That said I think this question is about general understanding, hence duplicate of [What is the difference between a 'closure' and a 'lambda'?](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) – nawfal Jul 05 '14 at 12:34

4 Answers4

120

A lambda may be implemented using a closure, but it is not itself necessarily a closure.

A closure is "a function together with a referencing environment for the non-local variables of that function.".

When you make a lambda expression that uses variables defined outside of the method, then the lambda must be implemented using a closure. For example:

int i = 42;

Action lambda = () => { Console.WriteLine(i); }; 

In this case, the compiler generated method must have access to the variable (i) defined in a completely different scope. In order for this to work, the method it generates is a "function together with the referencing environment" - basically, it's creating a "closure" to retrieve access to the variable.

However, this lambda:

Action lambda2 = () => { Console.WriteLine("Foo"); }

does not rely on any "referencing environment", since it's a fully contained method. In this case, the compiler generates a normal static method, and there is no closure involved at all.

In both cases, the lambda is creating a delegate ("function object"), but it's only creating a closure in the first case, as the lambda doesn't necessarily need to "capture" the referencing environment in all cases.

SharpC
  • 6,974
  • 4
  • 45
  • 40
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 3
    `var lambda2 = () => { Console.WriteLine("Foo"); }` *Does not rely on any "referencing environment", since it's a fully contained method.* It closes over the IO system! :) – Daniel Earwicker Mar 06 '12 at 20:52
  • @DanielEarwicker I wouldn't consider a .NET reference as closing over the system. Your setting up the operational environment in which the function operates, not creating an environment specifically for the function itself (which is passed with it). There is a difference. – Reed Copsey Mar 06 '12 at 20:59
  • 1
    It was only a half-serious comment - yes, there is no need for the C# compiler to generate a special class to represent a closure. But in general terms a closure is any situation where a function that is dependent on some value that is not passed in a formal parameter. In that sense, even a simple C program, with a function referring to a global variable, is an example of closure. – Daniel Earwicker Mar 06 '12 at 21:18
  • @DanielEarwicker Yes - but by that definition, pretty much any software is a "closure" as its always dependent upon its operating environment... Not sure how you'd make software that wasn't a closure by that definition... – Reed Copsey Mar 06 '12 at 21:20
  • 2
    Note that you cannot use "var" with lambdas in C# because lambdas are typeless. – Eric Lippert Mar 06 '12 at 21:21
  • @ReedCopsey - Yes, most real software closes over the file system at least. But you could say that in a UNIX-like system, standard input is a formal parameter and standard output is the result, so a program like `sort` is a pure function, as its result depends on its parameter. – Daniel Earwicker Mar 06 '12 at 21:58
  • 2
    I'd look at the second example as a degenerate case, but still a closure. Your definition says a closure is "a function together with a referencing environment for the non-local variables of that function.". In this example, there are no non-local variables, so as an implementation detail no environment information needs to be packed up. – kvb Mar 07 '12 at 01:45
  • @kvb Personally, I like to think of it as a separate concern. If you think about what the compiler has to do to make this work, it really helps make closures more understandable in general... The second is just a normal function, like any other. The first requires "something else" to be created. – Reed Copsey Mar 07 '12 at 02:01
  • @ReedCopsey - it's an interesting difference in perspective. I'm interested in the semantics as a user of the language, not as a compiler writer. Thus, I'd say that anonymous methods in C# are closures; they close over the local variables used within them. It's just that in the second case this is trivially true since there are no such variables. That's not to say that a more implementation-focused description is incorrect. – kvb Mar 07 '12 at 04:04
  • @kvb But, by that definition, every method would be a closure. A lambda is just another syntax to define a method... – Reed Copsey Mar 07 '12 at 17:04
  • @ReedCopsey Not every Method CAN close over local variable though, correct? So because Lambda's can close over local variables, I can see why kvb would just blanketly refer to them as closures. – Stefan H Mar 12 '12 at 21:39
  • @StefanH It can - if you write your own "closure" for it - but the thing is, not every lambda does (or needs to) close over a local - many don't... – Reed Copsey Mar 12 '12 at 22:16
84

Reed's answer is correct; I would just add few additional details:

  • lambda expressions and anonymous methods both have closure semantics; that is, they "capture" their outer variables and extend the lifetimes of those variables.

  • anonymous function is the term we use when we mean a lambda expression or an anonymous method. Yes, that is confusing. Sorry. It was the best we could come up with.

  • a function that can be treated as an object is just a delegate. What makes a lambda a closure is that it captures its outer variables.

  • lambda expressions converted to expression trees also have closure semantics, interestingly enough. And implementing that correctly was a pain in the neck, I tell you!

  • "this" is considered an "outer variable" for the purpose of creating a closure even though "this" is not a variable.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    While `this` isn't actually a variable, I don't think it's too surprising that it would be treated as one for the purposes of closure semantics. It behaves very similarly to how a read-only "variable" would behave. As well, I think it's intuitively part of the context that a closure is intended to capture. Finally, it's one instance where the false (though common, it seems) assumption that closures capture values is not too damaging: `this` certainly isn't going to changed after the fact! – dlev Mar 06 '12 at 21:42
  • 6
    @dlev: it is unsurprising for "this" in a reference type. In a value type, sometimes people take advantage of the fact that "this" is logically *an alias to the variable that contains the value of the struct*; closing over "this" when in a method of a mutable value type can produce unexpected results. – Eric Lippert Mar 06 '12 at 23:36
12

It's "closure" not "clojure."

That is not what a closure is. A closure is basically a representation of a function together with any non-local variables that the function consumes.

In that sense, lambdas are not closures, but they do cause closures to be generated by the compiler if they close over any variables.

If you use ILDASM on an assembly that contains a lambda that closes over some variables, you will see in that assembly a compiler generated class that repsresents the function and those variables that were closed over. That is the closure.

When you say

functions that are treated as objects,

that's normally just "function object" (in C# we'd say "delegate") and is common in functional programming.

jason
  • 236,483
  • 35
  • 423
  • 525
11

Yes. Closures typically capture variables from the outer scope. Lambdas can do that. However if your lambda does not capture anything, it is not a closure.

usr
  • 168,620
  • 35
  • 240
  • 369
  • By this definition would a lambda taking no external variables be a closure? – Yuck Mar 06 '12 at 20:42
  • 2
    Lambdas *may* do that. Jason's answer is more accurate. – Daniel Earwicker Mar 06 '12 at 20:42
  • The term "closure" might be well defined, but it is used loosely in practice. I don't think it can be definitely said that lambdas which capture nothing are not closures. – usr Mar 06 '12 at 20:44
  • 3
    @usr Probably used loosely because its definition is not well understood. So, it's really just being used *incorrectly*. – Yuck Mar 06 '12 at 20:45
  • @usr - A good example of misuse of the term was the early stages (the first five years!) of discussion of adding lambdas to Java. The new syntax was referred to as the "closure" feature. More recently they've switched to calling it lambda, in acknowledgement that it's the right term to use. It may or may not involve closure depending on what the lambda body says. – Daniel Earwicker Mar 06 '12 at 20:50